我怎样才能完成ThreadPool.Join?
我正在编写一个使用 ThreadPool.QueueUserWorkItem() 的 Windows 服务。每个线程都是一个短暂的任务。
当服务停止时,我需要确保当前正在执行的所有线程都已完成。有什么方法可以等待队列自行清除吗?
I am writing a windows service that uses ThreadPool.QueueUserWorkItem()
. Each thread is a short-lived task.
When the service is stopped, I need to make sure that all the threads that are currently executing complete. Is there some way of waiting until the queue clears itself?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
执行此操作的标准模式是使用一个计数器来保存待处理工作项的数量,以及一个在计数器达到零时发出信号的
ManualResetEvent
。这通常比为每个工作项使用WaitHandle
更好,因为当存在大量同时工作项时,它不能很好地扩展。另外,某些静态WaitHandle
方法无论如何只接受最多 64 个实例。The standard pattern for doing this is to use a counter which holds the number of pending work items and one
ManualResetEvent
that is signalled when the counter reaches zero. This is generally better than using aWaitHandle
for each work item as that does not scale very well when there are a lot of simultaneous work items. Plus, some of the staticWaitHandle
method only accept a maximum of 64 instances anyway.您可以在每个线程中创建一个事件(例如
ManualResetEvent
),并将其保存在同步列表中(使用lock
构造)。任务完成后设置事件或将其从列表中删除。当你想加入时,可以使用
WaitHandle.WaitAll
(MSDN 文档)等待所有事件发出信号。这是一个黑客,但我不知道如何将其简化为更简单的东西!
编辑:另外,您可以确保没有发布新事件,然后等待几秒钟。如果它们确实是短暂的,那么你就不会有问题。更简单,但更hacky。
最后,如果只是很短的时间,服务将不会退出,直到所有线程都死掉(除非它们是后台线程);因此,根据我的经验,如果时间很短,服务控制管理器不会介意一秒钟左右 - 您可以让它们过期。
You could create an event (e.g.
ManualResetEvent
) in each thread, and keep it in a synchronised list (using thelock
construct). Set the event or remove it from the list when the task is finished.When you want to join, you can use
WaitHandle.WaitAll
(MSDN documentation) to wait for all the events to be signalled.It's a hack, but I can't see how to reduce it to anything simpler!
Edit: additionally, you could ensure that no new events get posted, then wait a couple of seconds. If they are indeed short-lived, you'll have no problem. Even simpler, but more hacky.
Finally, if it's just a short amount of time, the service won't exit until all threads have died (unless they are background threads); so if it's a short amount of time, the service control manager won't mind a second or so - you can just leave them to expire - in my experience.