Microsoft has an article about creating a Task Scheduler that limits maximum concurrency:
How to: Create a Task Scheduler That Limits the Degree of Concurrency
The provided example class is clunky and kinda hard to grasp. I’ve been searching for a simple way to create a “thread pool” with limited concurrency. I previously experimented with ConcurrentBags of BackgroundWorkers – this worked, but it was also fairy complex and cumbersome.
The solution I came up with uses a Semaphore (or rather the lighter weight SemaphoreSlim type) to manage concurrency.
Simply put – you create a semaphore with a maxCount (and initialCount) equal to the max concurrency you desire. Then when you want to fire off a Task, first call semaphore.Wait(), then call semaphore.Relase() in a ContinueWith().
Contrived example:
public class LimitedAsync { private SemaphoreSlim _semaphore; public LimitedAsync(int maxConcurrency) { // Create semaphore with maxConcurrency slots _semaphore = new SemaphoreSlim(maxConcurrency, maxConcurrency); } public void DoSomethingAsync(string param) { //Wait for semaphore to have availablilty (blocks if semaphore is full) _semaphore.Wait(); //Run DoSomething in a task, then release slot in semaphore //ContinueWith is called even if DoSomething faults Task.Factory.StartNew(() => DoSomething(param)).ContinueWith((x) => _semaphore.Release()); } public void DoSomething(string param) { System.Threading.Thread.Sleep(500); } }