我有一个包含摘要条目的数据表,我的软件需要通过并访问Web服务以获取详细信息,然后将这些详细信息记录回数据库。在调用Web服务并等待响应时同步循环遍历表太慢(有数千个条目)所以我想取结果(一次10个左右)并将其解压缩以使其执行10同时进行操作。
我对C#线程的体验至少可以说,所以最好的方法是什么? .NET是否有某种线程安全队列系统,我可以用它来确保结果得到正确处理并按顺序排列?
答案 0 :(得分:5)
.NET是否有某种线程安全队列系统,我可以用它来确保结果得到正确处理并按顺序处理?
这是在.NET 4中添加的内容。默认情况下,BlockingCollection<T>
类充当生产者/消费者方案的线程安全队列。
通过将一个或多个元素添加到集合中,可以非常轻松地创建从集合和流程中“消耗”的多个元素。
答案 1 :(得分:5)
根据.NET Framework的哪个版本,您有两个不错的选择。
您可以在任何版本中使用ThreadPool.QueueUserWorkItem
。
int pending = table.Rows.Count;
var finished = new ManualResetEvent(false);
foreach (DataRow row in table.Rows)
{
DataRow capture = row; // Required to close over the loop variable correctly.
ThreadPool.QueueUserWorkItem(
(state) =>
{
try
{
ProcessDataRow(capture);
}
finally
{
if (Interlocked.Decrement(ref pending) == 0)
{
finished.Set(); // Signal completion of all work items.
}
}
}, null);
}
finished.WaitOne(); // Wait for all work items to complete.
如果您使用的是.NET Framework 4.0,则可以使用Task Parallel Library。
var tasks = new List<Task>();
foreach (DataRow row in table.Rows)
{
DataRow capture = row; // Required to close over the loop variable correctly.
tasks.Add(
Task.Factory.StartNew(
() =>
{
ProcessDataRow(capture);
}));
}
Task.WaitAll(tasks.ToArray()); // Wait for all work items to complete.
还有许多其他合理的方法可以做到这一点。我突出了上面的模式,因为它们很容易并且运行良好。在没有具体细节的情况下,我无法确定这两者是否适合您的情况,但它们应该是一个很好的起点。
<强>更新强>
我有一段短暂的大脑活动。如果你有TPL可用,你也可以使用Parallel.ForEach
作为一种比我上面提到的所有Task
hocus-pocus更简单的方法。
Parallel.ForEach(table.Rows,
(DataRow row) =>
{
ProcessDataRow(row);
});