检测线程组何时完成的最佳实践

发布于 2024-07-15 07:42:19 字数 1126 浏览 6 评论 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());

What's the best practice for detecting when a whole group of threads are done processing? I have a process that will query a [long running] web service for an arbitrary number of objects, and then needs to take a transactional action when all of them have completed successfully. I am currently running them asynchronously, using delegates from the .Net thread pool. Running them synchronously, defeats the purpose of running them on multiple threads... How else can I detect when ALL are finished? I though of using a coounter, (aka COM referece count) incrementing it for reach thread that starts and decrementing it in a callback function, and of keeping a dynamic list with a reference to each thread in it, to explicitly keep track of each one as they complete, but both of these solutions seem kinda kludgy...

Thanks to all... Based on yr suggestions, and on need to pass an object instance to the aynchronous thread, (represented by ref variable uPL below), I am using the following code... NOTE: IEEDAL.GetUsagePayloadReadings(uPL1) is the remote web service call

    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());

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

泪痕残 2024-07-22 07:42:19

您可以使用WaitHandle.WaitAll

You can use WaitHandle.WaitAll.

嗼ふ静 2024-07-22 07:42:19

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

The best way I've seen to do this is to use a countdown latch. There's a very good description, including C# source, in the May 2007 issue of MSDN Magazine.

七分※倦醒 2024-07-22 07:42:19

有几个选择。

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

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

There are a couple of options.

A Semaphore lets you have a counter used across all of your threads. If you know exactly how many there are, you can use this to check for when they're completed.

Another potential alternative is to have a ResetEvent for each thread. Just set the event at the "end" of the thread, and check them in your main thread. This may be more difficult, though.

酒绊 2024-07-22 07:42:19

我不知道这是否是一种“最佳实践”,但是 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() );

I don't know if it's a "best practice" or not, but the System.Threading.ManualResetEvent and System.Threading.WaitHandle classes are two classes that I find indispensable when threads need to signal one another. Here is a rudimentary example of how to use them with ThreadPool threads.

    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() );
七七 2024-07-22 07:42:19
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文