How to: Use a Thread Pool (C# Programming Guide)
A thread pool is a collection of threads that can be used to perform a number of tasks in the background. (See Using Threading for background information.) This leaves the primary thread free to perform other tasks asynchronously.
Thread pools are often employed in server applications. Each incoming request is assigned to a thread from the thread pool, so the request can be processed asynchronously, without tying up the primary thread or delaying the processing of subsequent requests.
Once a thread in the pool completes its task, it is returned to a queue of waiting threads, where it can be reused. This reuse enables applications to avoid the cost of creating a new thread for each task.
Thread pools typically have a maximum number of threads. If all the threads are busy, additional tasks are placed in queue until they can be serviced as threads become available.
You can implement your own thread pool, but it is easier to use the thread pool provided by the .NET Framework through the ThreadPool class.
The following example uses the .NET Framework thread pool to calculate the Fibonacci
result for ten numbers between 20 and 40. Each Fibonacci
result is represented by the Fibonacci
class, which provides a method called ThreadPoolCallback
that performs the calculation. An object representing each Fibonacci value is created, and the ThreadPoolCallback
method is passed to QueueUserWorkItem, which assigns an available thread in the pool to execute the method.
Because each Fibonacci
object is given a semi-random value to compute, and because each of the ten threads will be competing for processor time, there is no way to know in advance how long it will take for all ten results to be calculated. That's why each Fibonacci
object is passed an instance of the ManualResetEvent class during construction. Each object signals the provided event object when its calculation is complete, which allows the primary thread to block execution with WaitAll until all ten Fibonacci
objects have calculated a result. The Main
method then displays each Fibonacci
result.
Example
using System;
using System.Threading;
public class Fibonacci
{
public Fibonacci(int n, ManualResetEvent doneEvent)
{
_n = n;
_doneEvent = doneEvent;
}
// Wrapper method for use with thread pool.
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine("thread {0} started...", threadIndex);
_fibOfN = Calculate(_n);
Console.WriteLine("thread {0} result calculated...", threadIndex);
_doneEvent.Set();
}
// Recursive method that calculates the Nth Fibonacci number.
public int Calculate(int n)
{
if (n <= 1)
{
return n;
}
return Calculate(n - 1) + Calculate(n - 2);
}
public int N { get { return _n; } }
private int _n;
public int FibOfN { get { return _fibOfN; } }
private int _fibOfN;
private ManualResetEvent _doneEvent;
}
public class ThreadPoolExample
{
static void Main()
{
const int FibonacciCalculations = 10;
// One event is used for each Fibonacci object
ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
Random r = new Random();
// Configure and launch threads using ThreadPool:
Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
for (int i = 0; i < FibonacciCalculations; i++)
{
doneEvents[i] = new ManualResetEvent(false);
Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]);
fibArray[i] = f;
ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
}
// Wait for all threads in pool to calculation...
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("All calculations are complete.");
// Display the results...
for (int i= 0; i<FibonacciCalculations; i++)
{
Fibonacci f = fibArray[i];
Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
}
}
}
Sample Output
launching 10 tasks... result calculated... result calculated... result calculated... result calculated... result calculated... result calculated... result calculated... result calculated... result calculated... result calculated... all calculations complete Fibonacci(22) = 17711 Fibonacci(25) = 75025 Fibonacci(32) = 2178309 Fibonacci(36) = 14930352 Fibonacci(32) = 2178309 Fibonacci(26) = 121393 Fibonacci(35) = 9227465 Fibonacci(23) = 28657 Fibonacci(39) = 63245986 Fibonacci(22) = 17711
See Also
Tasks
Monitor Synchronization Technology Sample
Wait Synchronization Technology Sample
Reference
Threading (C# Programming Guide)
Using Threading (C# Programming Guide)
Mutex
WaitAll
ManualResetEvent
Set
ThreadPool
QueueUserWorkItem
ManualResetEvent
Concepts
Other Resources
Security in the .NET Framework
HOW TO: Synchronize Access to a Shared Resource in a Multithreading Environment by Using Visual C# .NET