Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does ThreadPool.RegisterWaitForSingleObject block the current thread or a thread-pool thread?

From reading the documentation of the ThreadPool.RegisterWaitForSingleObject method, it is not clear whether:

  1. It blocks the current thread while waiting on the EventWaitHandle and then commissions the WaitOrTimerCallback on a thread pool thread, or

  2. It commissions a thread pool thread to wait on the wait handle and then on that same thread execute the WaitOrTimerCallback once the wait handle has been signaled.

  3. It blocks the current thread and when the wait handle is signaled, it calls the WaitOrTimerCallback on the current thread. But this would be the equivalent functionality of WaitHandle.WaitOne(). Also, it would not involve the thread pool at all.

Which of the three does it do?

like image 808
Water Cooler v2 Avatar asked May 28 '16 13:05

Water Cooler v2


People also ask

When to use ThreadPool?

If you have a lot of small tasks, you can use a thread pool. The pool allocates threads only once and re-uses them to avoid unnecessary thread creation.

What is the use of ThreadPool QueueUserWorkItem method?

QueueUserWorkItem(WaitCallback, Object) Queues a method for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available.

When using a thread pool what happens to a given thread after it finishes?

Once a thread in the thread pool completes its task, it's returned to a queue of waiting threads. From this moment it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task.


1 Answers

It is none of the above, 2) is closest. The exact details are pretty convoluted, most of the code is buried in the CLR and it has changed across .NET versions. You can have a look-see at the current version in the CoreCLR source, I'll give the 10,000 feet view.

Key is that it doesn't block, the work is done by a dedicated unmanaged thread. Called the "wait thread" in the source code, it uses the WaitForMultipleObjects() winapi function to wait on all registered waits. If there is none (left) it just sleeps. The thread is woken up from either by a QueueUserApc() if the wait list changes so it can resume waiting with an updated list.

Once one of the wait objects get signaled, it uses ThreadPool.QueueUserWorkItem() to invoke the callback delegate target on a threadpool thread. If the executeOnlyOnce argument was true then the wait handle is removed from the list. And it quickly resumes waiting with WFMO. The thread never ends.

The executeOnlyOnce argument is important btw, hilarity ensues if you pass false and you use a ManualResetEvent. The thread explosion triggered by the MRE's Set() method is an interesting artifact to observe :) You can see the wait thread in the debugger's Debug > Windows > Threads when you enable unmanaged debugging. It doesn't have an interesting name however.

like image 145
Hans Passant Avatar answered Sep 27 '22 19:09

Hans Passant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!