Threading Simplified: Part 5 (Thread Pools)

I am again here to continue the discussion around Threading. Today we will discuss about Thread Pool and related concepts.

In case, you didn’t have a look at our previous posts, you can go through the following,

Let’s begin the discussion by putting questions as in the following,

What is Thread Pool

Thread pool is a collection or queuing of threads that can be used to execute various tasks in the background. It enforces notion of reusability instead of creating new threads all the time.

Once any thread is done with the assigned task, it comes back in the queue of waiting threads to be reused for some other task.

Why we need it

Thread pool executes the task in background and it helps the main thread to avoid blocking or waiting for long running tasks.

When to use it?

Typically it is used when we want to execute many short lived tasks. One example could be the server application when we have batch processing involved.

How we can use it?

There are several ways to use them as in the following:

  • Using QueueUserWorkItem method.
  • Using Asynchronous delegates.
  • Using BackgroundWorker [Will discuss in upcoming articles].
  • Using TPL [Task Parallel Library] [Will discuss in upcoming articles].

Using ThreadPool.QueueUserWorkItem method:

Let’s see how to create pooled threads via QueueUserWorkItem.

  1. static void Main(string[] args)  
  2. {  
  3.     Console.Title = "Thread Pool Demo";  
  4.     ThreadPool.QueueUserWorkItem(DoWork);  
  5.     ThreadPool.QueueUserWorkItem(DoWork, "ABC"); //With parameter  
  6. }  
  7. static void DoWork(object data)  
  8. {  
  9.     Console.WriteLine("I am a pooled thread using QueueUserWorkItem. My value: {0}", data);  
  10. }  


Please note that the callback method needs to have a parameter of object type, even if you don’t pass it while calling. This is required due to delegate signature.

Using Asynchronous delegates

Asynchronous delegate solves the few constrains or issues which are there with ThreadPool.QueueUserWorkItem method as in the following,
  • There is no easy way to get return value from callback method when using QueueUserWorkItem. Asynchronous delegates addresses this constraint.

  • Unhandled exceptions in the case of QueueUserWorkItem, needs to be handled explicitly in callback method whereas with Asynchronous delegates, these exceptions can be easily re-thrown to the original thread or the thread which calls EndInvoke.

Now let’s have a look how to create pooled threads via Asynchronous delegates.

  1. static void Main(string[] args)  
  2. {  
  3.     Console.Title = "Thread Pool Demo";  
  4.     Func < stringint > MethodName = GetStringLength;  
  5.     IAsyncResult result = MethodName.BeginInvoke("TestAsyncDelegates"nullnull);  
  6.     //Other code which can run in parallel  
  7.     int stringLength = MethodName.EndInvoke(result);  
  8.     Console.WriteLine("string length is: {0}", stringLength);  
  9. }  
  10. static int GetStringLength(string inputString)  
  11. {  
  12.     Console.WriteLine("I am a pooled thread using AsynchronousDelegates. My value: {0}", inputString);  
  13.     return inputString.Length;  
  14. }  



As you can see in the above screenshot that first message printed using callback method GetStringLength and the second message printed in the calling thread with the value returned from callback method.

Also please note that pooled thread are always background. You can test this by putting the following code in the callback method.
  1. Console.WriteLine("Is background thread? {0}", Thread.CurrentThread.IsBackground);  
To check if any thread is pooled thread or not, we can use the property provided by thread class as in the following in the callback method.
  1. Console.WriteLine("Is polled thread? {0}", Thread.CurrentThread.IsThreadPoolThread);  


Hope you have liked the article. Looking forward for your comments/suggestions.