This post is a part of preparation for 70-483 exam. Information written down here refers to the part Manage program flow.
Last time I wrote about the Thread class which allows you to run the code concurrently. Today I will show an another part of the System.Threading namespace, the ThreadPool class. It simply provides a pool of ready to use threads that can be used later on in the application. The main purpose and the way of working is similar to the database connection pool.
Creating a thread is an expensive process, it turns the application into sleeping state and it costs you time. Despite some limitations I will mention later, the thread pool is a remedy which helps to deal with this problem and improves the performance of the application.
You can treat it as a rental store with threads. You come there when you have some work to do. When the job is done the thread gets back to the pool and can be reused later for another task. Remember that the threads are being reused and they also reuse the local state. You have to be aware that the local state can be potentially shared between multiple operations.
There are three ways how the pool can behave when it is requested for a thread. Behavior depends on the current state. If there is a thread idle in the pool it will be returned immediately to you. Otherwise, if the maximum number of threads wasn’t exceeded, the pool creates a new thread to execute the task. The third option is that the job will be queued and will have to wait for the first available thread.
Be aware, that the thread pool has the limit of threads, it can’t grow to infinity.
The maximum number of threads in the thread pool is different for different versions of .NET and should be treated as an implementation detail. In .NET 2.0 there were 25 threads per core, in .NET 3.5 there were 250, and in .NET 4 there are 1,023 threads for the 32-bit applications and 32,767 threads for the
64-bit applications.MCSD Certification Toolkit
Think about the limits whenever you will use threads. If it’s possible the application will need more threads take into consideration creating threads manually instead of using thread pool. It will take more time to set up the threads but, on the other side, will increase level of parallelism as well. Besides the number there is a bunch of other differences between creating threads manually and using the thread pool.
- All the threads from the thread pool are background threads, whereas the manually created threads are foreground threads by default and can be set as background threads as well.
- You can’t abort or interrupt a thread from the thread pool.
- Threads from the thread pool are reused when they finish their work, whereas the normal
threads are destroyed. - You can’t control the priority of a thread from the thread pool.
- You don’t know when the thread finishes its work. There is no Join method or
something similar.
Usage
Take a look on the example of using the ThreadPool class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System; using System.Threading; ThreadPool.QueueUserWorkItem((state) => { Console.WriteLine("Additional thread started."); for(int i = 0; i< 5; i++) { Console.WriteLine("Additional thread is counting: {0}", i); Thread.Sleep(300); } }); public static class Worker{ public static void Todo(object iterations){ Console.WriteLine("Another one thread started."); for(int i = 0; i< (int)iterations; i++) { Console.WriteLine("Another one is counting: {0}", i); Thread.Sleep(100); } } } ThreadPool.QueueUserWorkItem(new WaitCallback(Worker.Todo), 5); Thread.Sleep(2000); |
As you can see usage of the ThreadPool class is simple. It is a static class and one of its methods is QueueUserWorkItem which takes a delegate with work item to execute. Second overload allows to pass data into the work item. It is passed via object state argument of the delegate.
The class has a few more methods but in most cases you won’t need them so I focused only on the basic one.
Summary
Thread pool is a different option for using threads. I explained how it works, how to use it and how it differs from using Thread class. Because of the differences and the limits always think which solution the best suits your needs. Remember, that each one has pros and cons.
The above example is available at github.
Pingback: [EN] Exam 70-483 Programming in C# - Introduction - Tymoteusz Kęstowicz .NET developer blog