2011-11-17 49 views
8

我有一个充满总结条目的数据表,我的软件需要通过并访问Web服务以获取详细信息,然后将这些详细信息记录回数据库。在调用Web服务并等待响应时同步循环访问表(因为有成千上万的条目),所以我想要将结果(每次10个左右)结果并进行线程处理,以便执行10操作同时进行。管理针对数据库队列的线程池的最佳方法

我对C#线程的经验仅限于说至少,所以最好的方法是什么? .NET是否有某种线程安全队列系统,我可以使用它来确保结果得到正确处理并按顺序处理?

+2

您使用的是什么版本的.Net? .NET 4中的多线程编程有很大的改进。 – svick

+0

应该包括那个..目前的目标是3.5,但是我可以在没有太多麻烦的情况下去4.0。 –

回答

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); 
    }); 
+0

顺便说一句,如果从Microsoft网站下载Reactive Extensions backport,实际上可以使用3.5中的TPL。 –

+0

令人敬畏的东西 - 非常感谢大家。看起来有几种方法来剥皮这只猫! –

+0

只有一件事(我知道,我会去RTFM!),但这是如何扩展的?我会做成千上万的这些行,我绝对不想同时启动数千个线程。我假设(希望?)内置了某种限制,所以这不会导致用户的计算机停机。 –

5

.NET是否有某种线程安全队列系统,我可以使用它来确保结果得到正确处理并按顺序处理?

这是一件由默认的.NET 4的BlockingCollection<T>类,补充,充当生产者/消费者场景一个线程安全的队列。

它可以很容易地创建一些从收集和处理中“消耗”的元素,同时添加一个或多个元素到集合中。

+0

非常好,我一定会检查出来。谢谢! –

+0

并发队列怎么样? http://msdn.microsoft.com/en-us/library/dd267265.aspx? – Dykam

+0

@Dykam'BlockingCollection ',默认情况下,包装'ConcurrentQueue '。虽然您可以直接使用CQ,但如果您想按照所述的方式在生产者/消费者场景中工作,BC会使这一过程更加简单。 –