使用 ThreadPool 跟踪失败工作线程的可靠方法
我正在寻找一种很好的方法来跟踪(计数)哪些工作人员在使用线程池排队并使用 WaitHandle.WaitAll() 来完成所有线程时失败。
联锁计数器是一种好技术还是有更强大的策略?
I'm looking for a good method of tracking (counting) which workers have failed when queued with a Threadpool and using WaitHandle.WaitAll() for all threads to finish.
Is Interlocking a counter a good technique or is there a more robust strategy?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,这是您可以采取的方法。我已将要跟踪的数据封装到
TrackedWorkers
类中。此类有一个构造函数,使您能够设置将有多少工作人员在工作。然后,使用LaunchWorkers
启动工作线程,这需要一个委托来接收object
并返回bool
。object
表示工作器的输入,bool
表示成功或失败,具体取决于true
或false
分别返回值。所以基本上我们所做的就是有一个数组来跟踪工作状态。我们启动工作程序并根据工作程序的返回值设置与该工作程序相对应的状态。当工作线程返回时,我们为所有要设置的
AutoResetEvents
设置一个AutoResetEvent
和WaitHandle.WaitAll
。请注意,有一个嵌套类来跟踪工作人员应该执行的工作(委托)、该工作的输入以及用于设置状态
AutoResetEvent
的ID
> 对应于该线程。请非常小心地注意,一旦工作完成,我们就不会保留对工作委托
func
或input
的引用。这很重要,这样我们就不会意外地阻止垃圾收集。有一些方法可以获取特定工作人员的状态,以及成功工作人员的所有索引和失败工作人员的所有索引。
最后一点:我不认为这段代码已经准备好用于生产。这只是我将采取的方法的一个草图。您需要注意添加测试、异常处理和其他此类细节。
使用示例:
上面的程序将启动 64 个线程。第 i 个线程的任务是将数字 i 和 2 * i 相加并将结果打印到控制台。但是,我添加了随机的睡眠量(少于一秒)来模拟繁忙状态,并掷硬币来确定线程的成功或失败。那些成功的打印他们被分配的任务的总和并返回
true
。那些失败的不打印任何内容并返回false
。这里我用过
Okay, here's an approach that you could take. I've encapsulated the data that we want to track into a class
TrackedWorkers
. There is a constructor on this class that enables you to set how many workers will be working. Then, the workers are launched usingLaunchWorkers
which requires a delegate that eats anobject
and returns abool
. Theobject
represents the input to the worker and thebool
represents success or failure depending ontrue
orfalse
being the return value, respectively.So basically what we do we have an array to track worker state. We launch the workers and set the status corresponding to that worker depending on the return value from the worker. When the worker returns, we set an
AutoResetEvent
andWaitHandle.WaitAll
for all theAutoResetEvents
to be set.Note that there is an nested class to track the work (the delegate) the worker is supposed to do, the input to that work, and an
ID
used to set the statusAutoResetEvent
corresponding to that thread.Note very carefully that once the work is done we are not holding a reference to the work delegate
func
nor to theinput
. This is important so that we don't accidentally prevent stuff from being garbage collected.There are methods for getting the status of a particular worker, as well as all the indexes of the workers that succeeded and all the indexes of the workers that failed.
One last note: I do not consider this code production ready. It is merely a sketch of the approach that I would take. You need to take care to add testing, exception handling and other such details.
Sample usage:
The above program is going to launch sixty-four threads. The
i
th thread has the task of adding the numbersi
and2 * i
and printing the result to the console. However, I have added a random amount of sleep (less than one second) to simulate busyness and I flip a coin to determine success or failure of the thread. Those that succeed print the sum they were tasked with and returntrue
. Those that fail print nothing and returnfalse
.Here I have used