0

检测整个线程组何时完成处理的最佳实践是什么?我有一个进程将查询 [长期运行] Web 服务以获取任意数量的对象,然后需要在所有对象都成功完成后采取事务操作。我目前正在使用 .Net 线程池中的委托异步运行它们。同步运行它们,违背了在多个线程上运行它们的目的......我还能如何检测所有何时完成?我虽然使用了一个计数器,(又名 COM 引用计数)为到达线程增加它,并在回调函数中减少它,并保留一个动态列表,其中包含对其中每个线程的引用,以显式跟踪每个线程当它们完成时,但这两种解决方案似乎都有些笨拙......

感谢所有人...根据您的建议,并且需要将对象实例传递给异步线程(由下面的 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());
4

5 回答 5

3

我见过的最好的方法是使用倒计时锁存器。在 2007 年 5 月的 MSDN 杂志上有很好的描述,包括 C# 源代码。

于 2009-03-16T15:39:59.453 回答
3

您可以使用WaitHandle.WaitAll

于 2009-03-16T14:15:14.917 回答
2

有几个选项。

信号量允许您在所有线程中使用一个计数器。如果您确切知道有多少,您可以使用它来检查它们何时完成。

另一种可能的替代方法是为每个线程设置一个 ResetEvent。只需将事件设置在线程的“末尾”,然后在主线程中检查它们。不过,这可能更困难。

于 2009-03-16T14:14:42.407 回答
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() );
于 2009-03-16T14:20:45.790 回答
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
于 2009-03-16T14:21:41.297 回答