ConcurrencyC#verifiedVerified

Thread Pool Pattern in C#

Maintain a fixed set of reusable worker threads that pick up tasks from a queue, avoiding the overhead of spawning a new thread per task.

How to Implement the Thread Pool Pattern in C#

1Step 1: Define a simple custom thread pool

public sealed class SimpleThreadPool : IDisposable
{
    private readonly Thread[] _workers;
    private readonly Channel<Action> _taskQueue;
    private bool _disposed;

    public SimpleThreadPool(int workerCount)
    {
        _taskQueue = Channel.CreateUnbounded<Action>();
        _workers = new Thread[workerCount];

2Step 2: Start worker threads

        for (var i = 0; i < workerCount; i++)
        {
            _workers[i] = new Thread(WorkerLoop)
            {
                IsBackground = true,
                Name = $"Pool-Worker-{i}"
            };
            _workers[i].Start();
        }
    }

3Step 3: Enqueue work items

    public void Submit(Action task) =>
        _taskQueue.Writer.TryWrite(task);

    private void WorkerLoop()
    {
        foreach (var task in _taskQueue.Reader.ReadAllAsync()
            .ToBlockingEnumerable())
        {
            try { task(); }
            catch (Exception ex)
            {
                Console.WriteLine($"Task error: {ex.Message}");
            }
        }
    }

    public void Dispose()
    {
        if (_disposed) return;
        _disposed = true;
        _taskQueue.Writer.Complete();
        foreach (var w in _workers) w.Join(1000);
    }
}

Thread Pool Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Thread Pool Pattern in the Real World

A hotel concierge desk staffed by three concierges represents the thread pool. No matter how many guests check in, only three requests are handled simultaneously. Other guests wait in the lobby queue. When a concierge finishes, they immediately assist the next waiting guest — the staff are never created or dismissed per guest, they simply stay on duty.