How can I execute ThreadPool.Join?

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 threads currently running are complete. Is there any way to wait until the queue is cleared?

+5
source share
2 answers

You can create an event (for example, ManualResetEvent ) in each thread and save it in a synchronized list (using the lock construct). Set an event or remove it from the list when the task is completed.

If you want to join, you can use WaitHandle.WaitAll ( MSDN documentation ) to wait for all events to be signaled.

It’s a hack, but I don’t see how to reduce it to something simpler!


Edit: In addition, you can guarantee that new events will not be published, and then wait a couple of seconds. If they are really short-lived, you will not have a problem. Even simpler, but more hacks.

Finally, if this is just a short period of time, the service will not exit until all threads die (if they are not background threads); therefore, if this is a short period of time, the service control manager will not mind for a second or so - you can just leave them on time - in my experience.

+8
source

The standard template for this is to use a counter that contains the number of pending work items and one ManualResetEvent that is signaled when the counter reaches zero. This is usually better than using WaitHandle for each work item, as it does not scale very well when there are many simultaneous work items. In addition, some static WaitHandle methods allow only 64 instances.

 // 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(); 
+3
source

Source: https://habr.com/ru/post/900091/


All Articles