Dirt simple method of limiting System.Threading.Task concurrency (max concurrent threads)

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:

[csharp]
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);
}
}
[/csharp]

Leave a Comment

Your email address will not be published. Required fields are marked *