Проблема, повторяющаяся по строкам DataTable несколько раз - PullRequest
1 голос
/ 23 августа 2011

:: РЕДАКТИРОВАТЬ ::

Хорошо, ребята, кажется, что я все-таки идиот.Эта проблема не имела никакого отношения к моему коду, а к тому, что Visual Studio перезаписала мою базу данных SQLite предыдущей (и пустой) версией.Похоже, что идет большая дискуссия о безопасности потоков, поэтому я постараюсь прочитать больше!

:: / EDIT ::

Я пытаюсь использовать несколько фоновых рабочих.циклически проходить по строкам базы данных по 100 записей одновременно, избегая дублирования, но у меня, похоже, возникают некоторые проблемы.По сути, я начинаю с создания 10 фоновых рабочих в цикле и добавления их в список.Затем я перебираю фоновые рабочие в Списке, и для каждого из них выполняю RunWorkerAsync (), а затем сплю основной поток в течение 5 секунд.Внутри метода DoWork каждого фонового работника у меня есть работник, который выбирает 100 строк из базы данных, где для определенного поля установлено значение по умолчанию.Отсюда я хочу сначала пройтись по каждой возвращаемой строке и изменить это значение по умолчанию на значение «В процессе», а затем снова выполнить цикл по значениям и фактически выполнить обработку, необходимую для поиска правильных значений для этих полей.Кажется, у меня проблема в том, что после первой итерации результатов у меня появляется пустой DataTable, и я подозреваю, что мои проблемы возникают из-за мелкого копирования.Вот код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Text;
using DBFill.GeoCodeService;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;

namespace DBFill {
    class Program {
        public static int completedGeocodes = 0;
        static void Main(string[] args) {
            SQLiteDatabase db = new SQLiteDatabase("zipCodes.s3db");
            List<BackgroundWorker> workers = new List<BackgroundWorker>();
            for (int i = 0; i < 10; i++) {
                BackgroundWorker b = new BackgroundWorker();
                b.DoWork += new DoWorkEventHandler(worker_DoWork);
                b.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                b.WorkerReportsProgress = true;
                b.ProgressChanged += new ProgressChangedEventHandler(b_ProgressChanged);
                workers.Add(b);
            }
            int counter = 0;
            foreach (BackgroundWorker b in workers) {
                Debug.WriteLine("Worker {0} is starting.", counter);
                b.RunWorkerAsync(b);
                counter++;
                System.Threading.Thread.Sleep(5000);
            }
            Boolean running = true;
            while (running) {
                running = false;
                foreach (BackgroundWorker b in workers) {
                    Debug.WriteLine("Checking background Worker");
                    if (b.IsBusy) {
                        running = true;
                    }
                }
                System.Threading.Thread.Sleep(5000);
            }

        }

        static void b_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            Console.WriteLine(".");
        }

        static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {

        }

        static void worker_DoWork(object sender, DoWorkEventArgs e) {
            BackgroundWorker b = (BackgroundWorker)e.Argument;
            SQLiteDatabase db = new SQLiteDatabase("zipCodes.s3db");
            DataTable results = get100Records();
            DataTable temp = DeepClone<DataTable>(results);//results;
            Dictionary<String, String> marker = new Dictionary<string, string>();
            marker["LATITUDE"] = "In Progress";
            foreach (DataRow row in temp.Rows) {
                Debug.WriteLine("Working with zip {0}", row["ZIP_CODE"]);
                db.Update("ZIP_CODES", marker, String.Format("ZIP_CODE = '{0}'", row["ZIP_CODE"]));
            }
            foreach (DataRow row in results.Rows) {
                String geoCodeResponse = GeoCodeZip(row["ZIP_CODE"].ToString());
                Debug.WriteLine(String.Format("Attempting Zip: {0}", row["ZIP_CODE"].ToString()));
                if (geoCodeResponse != "There was an error") {
                    marker["LATITUDE"] = geoCodeResponse.Split(',')[0];
                    marker["LONGITUDE"] = geoCodeResponse.Split(',')[1];
                    Console.WriteLine(String.Format("#{0} updated successfully", completedGeocodes));
                }
                else {
                    marker["LATITUDE"] = "Not Set";
                    Console.WriteLine(String.Format("#{0} failed", completedGeocodes));
                }
                db.Update("ZIP_CODES", marker, String.Format("ZIP_CODE = '{0}'", row["ZIP_CODE"]));
                db.ExecuteNonQuery("commit");
                b.ReportProgress(1);
                completedGeocodes++;
            }
        }

        private static DataTable get100Records() {
            SQLiteDatabase db = new SQLiteDatabase("zipCodes.s3db");
            DataTable results = db.GetDataTable("select ZIP_CODE from ZIP_CODES where LATITUDE = 'Not Set' LIMIT 100");
            return results;
        }

        private static String GeoCodeZip(String zip) {
            try {
                GeocodeRequest request = new GeocodeRequest();
                request.Credentials = new GeoCodeService.Credentials();
                request.Credentials.ApplicationId = "API_KEY";
                request.Query = zip;
                ConfidenceFilter[] filters = new ConfidenceFilter[1];
                filters[0] = new ConfidenceFilter();
                filters[0].MinimumConfidence = Confidence.High;
                GeocodeOptions opts = new GeocodeOptions();
                opts.Filters = filters;
                request.Options = opts;
                GeocodeServiceClient service = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
                GeocodeResponse response = service.Geocode(request);
                if (response.Results.Length > 0) {
                    return String.Format("{0},{1}", response.Results[0].Locations[0].Latitude, response.Results[0].Locations[0].Longitude);
                }
                else {
                    Debug.WriteLine(String.Format("{0}", response.ResponseSummary.FaultReason));
                    return "There was an error";
                }
            }
            catch (Exception e) {
                Debug.WriteLine(e.Message);
                return "There was an error";
            }
        }

        public static T DeepClone<T>(T obj) {
            using (var ms = new MemoryStream()) {
                var formatter = new BinaryFormatter();
                formatter.Serialize(ms, obj);
                ms.Position = 0;

                return (T)formatter.Deserialize(ms);
            }
        }

    }
}

Есть идеи?

1 Ответ

1 голос
/ 23 августа 2011

Кажется, что ваша задержка и почему вы хотите многопоточность, это не чтение записей из базы данных, а обращение к GeocodeServiceClient.

Вы можете попробовать переработать основной метод, чтобы последовательно извлекать все записи из БД и анализировать их.Затем вы разбиваете этот список на четные порции и раскручиваете фоновых рабочих, чтобы запускать их через службу Geocode.

Другой вариант - поместить записи в очередь, и каждый фоновый работник вытолкнет один из очереди для работы в очереди.затем вернитесь в очередь, пока еще есть необработанные записи.Вам нужно быть осторожным с блокировкой В C # было бы лучше использовать Queue.Synchronized или lock () для обеспечения безопасности потока? .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...