c#多线程循环数据表
本文关键字:数据表 循环 多线程 | 更新日期: 2023-09-27 18:08:59
我有一个datatable
和1000 records
。每行有一个带链接的列。我将循环datatable
并使用datatable
中的链接从网站获取记录。代码工作得很好,但是这花费了太多时间来检索记录。所以我需要在多个线程中传递它并获取记录,并将所有记录添加到单个datatable
。我正在使用C# , Visual studio 2015
.
我们如何使用threading C#
,任何帮助感谢。
现有代码如下:
for (int i = 0; i < dt.Rows.Count; i++)
{
String years = String.Empty;
dt.Rows[i]["Details"] = GetWebText(dt.Rows[i]["link"].ToString());
}
private String GetWebText(String url)
{
var html = new HtmlAgilityPack.HtmlDocument();
string text= html.LoadHtml(new WebClient().DownloadString(url));
return text;
}
您将在这里遇到数据表写操作的线程安全问题。因此,您需要确保所执行的操作是分开的。
好处是你实际上是在做三个不同的步骤,你可以很容易地把它们分开,并行化慢的部分,同时保持线程安全。
你的代码是这样做的:
var url = dt.Rows[i]["link"].ToString();
var webText = GetWebText(url);
dt.Rows[i]["Details"] = webText;
让我们按照这三个步骤处理数据,但只并行化GetWebText
部分。
是这样的:
var data =
dt
.AsEnumerable()
.Select(r => new { Row = r, Url = r["link"].ToString() })
.AsParallel()
// This `Select` is the only part run in parallel
.Select(x => new { x.Row, WebText = GetWebText(x.Url) })
.ToArray();
foreach (var datum in data)
{
datum.Row["Details"] = datum.WebText;
}
阻塞集合可以解决这个问题:
Blocking<string> links= new BlockingCollection<string>();'' using System.Collections.Concurrent;
Blocking<string> results= new BlockingCollection<string>();
public static void main()
{
//get your datatable
for (int i = 0; i < dt.Rows.Count; i++)
{
ThreadStart t = new ThreadStart(threads);
Thread th = new Thread(t);
th.Start();
}
for (int i = 0; i < dt.Rows.Count; i++)
{
links.add(dt.Rows[i]["link"].ToString());
}
for (int i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i]["Details"] = results.Take();
}
}
public void threads()
{
while(true)
{
string url= Links.take();//block if links is empty
var html = new HtmlAgilityPack.HtmlDocument();
string text= html.LoadHtml(new WebClient().DownloadString(url));
results.add(text);//add result to the other queue
}
}