如何完成 ThreadPool.Join?
Posted
技术标签:
【中文标题】如何完成 ThreadPool.Join?【英文标题】:How can I accomplish ThreadPool.Join? 【发布时间】:2011-03-26 11:57:50 【问题描述】:我正在编写一个使用ThreadPool.QueueUserWorkItem()
的Windows 服务。每个线程都是一个短暂的任务。
当服务停止时,我需要确保当前正在执行的所有线程都完成。有什么方法可以等到队列自行清除?
【问题讨论】:
【参考方案1】:您可以在每个线程中创建一个事件(例如ManualResetEvent
),并将其保存在同步列表中(使用lock
构造)。任务完成后设置事件或将其从列表中删除。
当您想加入时,您可以使用WaitHandle.WaitAll
(MSDN documentation) 等待所有事件发出信号。
这是一个 hack,但我不知道如何将其简化为更简单的方法!
编辑:另外,您可以确保没有发布新事件,然后等待几秒钟。如果它们确实是短暂的,那么您将没有问题。更简单,但更 hacky。
最后,如果只是很短的时间,服务不会退出,直到所有线程都死掉(除非它们是后台线程);所以如果时间很短,服务控制经理不会介意一秒钟左右 - 你可以让它们过期 - 根据我的经验。
【讨论】:
它们应该是短暂的,但对于我的用例,我需要比“应该工作”更多的保证。我正在考虑使用互锁线程计数器来跟踪池中的线程数,并等待等于零。 其实我比柜台更喜欢你的第一个建议。【参考方案2】:执行此操作的标准模式是使用一个计数器来保存待处理工作项的数量,以及一个ManualResetEvent
,当计数器达到零时发出信号。这通常比为每个工作项使用WaitHandle
更好,因为当有很多同时工作项时,它不能很好地扩展。另外,一些静态的WaitHandle
方法无论如何只接受最多64 个实例。
// Initialize to 1 because we are going to treat the current thread as
// a work item as well. This is to avoid a race that could occur when
// one work item gets queued and completed before the next work item
// is queued.
int count = 1;
var finished = new ManualResetEvent(false);
try
while (...)
Interlocked.Increment(ref counter);
ThreadPool.QueueUserWorkItem(
delegate(object state)
try
// Your task goes here.
finally
// Decrement the counter to indicate the work item is done.
if (Interlocked.Decrement(ref count) == 0)
finished.Set();
);
finally
// Decrement the counter to indicate the queueing thread is done.
if (Interlocked.Decrement(ref count) == 0)
finished.Set();
finished.WaitOne();
【讨论】:
以上是关于如何完成 ThreadPool.Join?的主要内容,如果未能解决你的问题,请参考以下文章
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thre
如何将图像和纹理添加到 Three.js JSON 对象文件
java.lang.RuntimeException: Handler (android.os.Handler) sending message to a Handler on a dead thre