检测整组线程何时完成处理的最佳做法是什么?我有一个进程将查询[长时间运行] Web服务以查找任意数量的对象,然后需要在所有对象成功完成时执行事务操作。我目前使用.Net线程池中的委托异步运行它们。同步运行它们会破坏在多个线程上运行它们的目的......我怎样才能检测到ALL何时完成?我虽然使用了一个coounter,(也称为COM referece count)将它递增到在回调函数中启动和递减它的到达线程,并保持动态列表中包含对每个线程的引用,以明确地跟踪每个当他们完成时,但这两种解决方案看起来都有点笨拙......
感谢所有...基于你的建议,并且需要将对象实例传递给异步线程,(由下面的ref变量uPL表示),我使用以下代码...注意:IEEDAL.GetUsagePayloadReadings (uPL1)是远程Web服务调用
foreach (MeterChannel chgChan in chgChs)
foreach (UsagePayload uPL in chgChan.IntervalPayloads)
{
ManualResetEvent txEvnt = new ManualResetEvent(false);
UsagePayload uPL1 = uPL;
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
if (!uPL1.HasData)
IEEDAL.GetUsagePayloadReadings(uPL1);
UsageCache.PersistPayload(uPL1);
SavePayLoadToProcessFolder(uPL1);
txEvnt.Set();
} );
waitHndls.Add(txEvnt);
}
WaitHandle.WaitAll(waitHndls.ToArray());
答案 0 :(得分:3)
您可以使用WaitHandle.WaitAll。
答案 1 :(得分:3)
我看到这样做的最好方法是使用倒计时锁存器。 2007年5月的MSDN杂志中有一个very good description,包括C#源代码。
答案 2 :(得分:2)
有几种选择。
Semaphore允许您在所有线程中使用计数器。如果您确切知道有多少,可以使用它来检查它们何时完成。
另一个可能的替代方案是为每个线程提供一个ResetEvent。只需在线程的“结尾”设置事件,并在主线程中检查它们。但这可能更难。
答案 3 :(得分:2)
我不知道它是否是“最佳实践”,但System.Threading.ManualResetEvent和System.Threading.WaitHandle类是两个类,当线程需要相互发信号时,我发现这两个类是必不可少的。以下是如何将它们与ThreadPool线程一起使用的基本示例。
List<WaitHandle> handles = new List<WaitHandle>();
for ( int iii = 0; iii < 10; iii++ ) {
ManualResetEvent transactionEvent = new ManualResetEvent( false );
ThreadPool.QueueUserWorkItem( delegate( object state ) {
// Do your work here...
transactionEvent.Set();
} );
handles.Add( transactionEvent );
}
WaitHandle.WaitAll( handles.ToArray() );
答案 4 :(得分:1)
Dim WaitAllEvents(1) As AutoResetEvent
Dim thread1 As Thread
Dim thread2 As Thread
thread1 = New Thread(AddressOf Thread1Worker)
thread2 = New Thread(AddressOf Thread2Worker)
WaitAllEvents(0) = New AutoResetEvent(False)
WaitAllEvents(1) = New AutoResetEvent(False)
thread1.Start()
thread2.Start()
'Main thread will wait until all instances of AutoResetEvent
'have become signaled with a call to Set()
WaitHandle.WaitAll(WaitAllEvents)
Console.WriteLine("All threads done exiting main thread")
thread2 = Nothing
thread1 = Nothing
'...
'...
Private Sub Thread1Worker()
Thread.Sleep(5000)
Console.WriteLine("Thread1 done")
WaitAllEvents(0).Set()
End Sub
Private Sub Thread2Worker()
Thread.Sleep(3000)
Console.WriteLine("Thread2 done")
WaitAllEvents(1).Set()
End Sub