Thread Pools in C#

A thread pool in C# is a collection of pre-created threads that can be reused to execute multiple tasks efficiently. Instead of creating new threads for each task, the thread pool manages a pool of worker threads, reducing the overhead of thread creation and destruction.

The ThreadPool class in the System.Threading namespace provides methods to queue work items for execution by background threads. When a thread completes its task, it returns to the pool and waits for the next available work item.

Syntax

Following is the syntax for queuing work items to the thread pool −

ThreadPool.QueueUserWorkItem(new WaitCallback(MethodName));

You can also use a lambda expression −

ThreadPool.QueueUserWorkItem(_ => MethodName());

Using ThreadPool with QueueUserWorkItem

The QueueUserWorkItem method queues a method for execution by a thread pool worker thread −

Example

using System;
using System.Threading;

class Program {
   static void Main() {
      Console.WriteLine("Main thread started");
      
      // Queue work items to thread pool
      for (int i = 1; i <= 5; i++) {
         int taskNumber = i;
         ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTask), taskNumber);
      }
      
      // Wait for all tasks to complete
      Thread.Sleep(3000);
      Console.WriteLine("Main thread finished");
   }
   
   static void ProcessTask(object state) {
      int taskId = (int)state;
      Console.WriteLine($"Task {taskId} started on thread {Thread.CurrentThread.ManagedThreadId}");
      
      // Simulate work
      Thread.Sleep(1000);
      
      Console.WriteLine($"Task {taskId} completed on thread {Thread.CurrentThread.ManagedThreadId}");
   }
}

The output of the above code is −

Main thread started
Task 1 started on thread 4
Task 2 started on thread 5
Task 3 started on thread 6
Task 4 started on thread 7
Task 5 started on thread 8
Task 1 completed on thread 4
Task 2 completed on thread 5
Task 3 completed on thread 6
Task 4 completed on thread 7
Task 5 completed on thread 8
Main thread finished

Using ThreadPool with Lambda Expressions

Modern C# allows using lambda expressions for simpler syntax −

Example

using System;
using System.Threading;

class Program {
   static void Main() {
      Console.WriteLine("Starting thread pool tasks");
      
      for (int i = 1; i <= 3; i++) {
         int taskId = i;
         ThreadPool.QueueUserWorkItem(_ => {
            Console.WriteLine($"Lambda Task {taskId} executing on thread {Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(500);
            Console.WriteLine($"Lambda Task {taskId} completed");
         });
      }
      
      Thread.Sleep(2000);
      Console.WriteLine("All tasks finished");
   }
}

The output of the above code is −

Starting thread pool tasks
Lambda Task 1 executing on thread 4
Lambda Task 2 executing on thread 5
Lambda Task 3 executing on thread 6
Lambda Task 1 completed
Lambda Task 2 completed
Lambda Task 3 completed
All tasks finished

ThreadPool vs Regular Threads

ThreadPool Regular Threads
Reuses existing threads from a pool Creates new thread instances each time
Background threads (cannot prevent app termination) Can be foreground or background threads
Limited control over thread properties Full control over thread creation and properties
Better performance for short-lived tasks Better for long-running operations

ThreadPool Configuration

You can configure the thread pool size using SetMinThreads and SetMaxThreads methods −

Example

using System;
using System.Threading;

class Program {
   static void Main() {
      // Get current thread pool settings
      ThreadPool.GetMinThreads(out int minWorker, out int minIO);
      ThreadPool.GetMaxThreads(out int maxWorker, out int maxIO);
      
      Console.WriteLine($"Min threads: Worker={minWorker}, IO={minIO}");
      Console.WriteLine($"Max threads: Worker={maxWorker}, IO={maxIO}");
      
      // Set custom thread pool size
      ThreadPool.SetMinThreads(4, 4);
      ThreadPool.SetMaxThreads(8, 8);
      
      Console.WriteLine("Thread pool configured");
      
      // Queue multiple tasks
      for (int i = 1; i <= 10; i++) {
         int taskId = i;
         ThreadPool.QueueUserWorkItem(_ => {
            Console.WriteLine($"Task {taskId} on thread {Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(100);
         });
      }
      
      Thread.Sleep(2000);
   }
}

The output of the above code is −

Min threads: Worker=4, IO=4
Max threads: Worker=32767, IO=1000
Thread pool configured
Task 1 on thread 4
Task 2 on thread 5
Task 3 on thread 6
Task 4 on thread 7
Task 5 on thread 8
Task 6 on thread 9
Task 7 on thread 10
Task 8 on thread 11
Task 9 on thread 4
Task 10 on thread 5

Conclusion

Thread pools in C# provide an efficient way to execute multiple short-lived tasks by reusing a collection of worker threads. They reduce thread creation overhead and are ideal for scenarios with many small, independent operations that don't require precise thread control.

Updated on: 2026-03-17T07:04:35+05:30

4K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements