多次在DataTable行中循环出现问题
本文关键字:循环 问题 DataTable | 更新日期: 2023-09-27 18:06:21
::编辑::
好吧,伙计们,看来我毕竟是个白痴。这个问题根本与我的代码无关,而是与Visual Studio用以前的(空的(版本覆盖了我的SQLite数据库有关。看起来确实有一个关于线程安全的伟大讨论正在进行,所以我会留下来阅读更多!
::/EDIT::
我试图使用多个后台工作程序一次循环遍历数据库的行100条记录,同时避免重复,但我似乎遇到了一些问题。基本上,我首先在一个循环中创建10个后台工作者,并将他们添加到列表中。然后,我循环遍历List中的后台工作程序,并对每个工作程序执行RunWorkersync((,然后使主线程休眠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);
}
}
}
}
有什么想法吗?
您的延迟以及为什么要对其进行多线程处理,似乎不是从数据库中读取记录,而是调用GeocodeServiceClient
。
您可以尝试重新设计您的主方法,以便按顺序从DB中获取所有记录并对其进行解析。然后,您将该列表拆分为偶数块,并启动后台工作程序,通过Geocode服务运行它们。
另一种选择是将记录放入队列中,让每个后台工作人员从队列中弹出一个记录,然后在仍有未处理的记录时返回队列。您需要小心锁定C#,使用Queue会更好吗。线程安全的同步或锁定((?。