Simple Task Throttling

A while ago Scott Hanselman posted an article where they compare various methods of asynchronous synchronisation. Scott and Stephen Toub came up with a little class called AsyncLock that utilises SemaphoreSlim and IDisposable to make a nice little utility to block more than one thread from accessing a piece of code at a time. In Xamling-Core we extended this so you can have named locks (like a file name for example).

Recently we extended it a little further to allow you to throttle calls, so same idea as the full lock, but you can let through a few at a time.

TaskThrottler.cs

For example, when resizing lots of images you could wrap your code in one of these ThrottleLocks and only four calls would run at a time.

TaskThrottler _getBlock = TaskThrottler.Get("ImageServiceProcess", 4);
using (var l = await _getBlock.LockAsync())
{
    var result = await _imageResizeService.ResizeImage(fn, variantFile, size);
    ...
}

Super simple.

Another adaption is allowing you to call the throttler directly to line up a bunch of processing then wait for the result.

There are two versions here – calling processes that return data and those that don’t.

With data returned:

List<Task<SomeEntity>> tasks = new List<Task<SomeEntity>>();

for (var i = 0; i < 500; i++)
{
    var t = TaskThrottler.Get("Test", 50).Throttle(_getAnEntity);
    tasks.Add(t);
    Debug.WriteLine("Added: {0}", i);
}

await Task.WhenAll(tasks);

...

async Task<SomeEntity> _getAnEntity()
{
    var t = new SomeEntity()
    {
        Count = ++count
    };

    await Task.Delay(1000);

    Debug.WriteLine("Actual: {0}", t.Count);

    return t;
}

You can of course call methods that don’t have any return value.

So there you have it, a simple light weight asynchronous throttling utility.

Jordan.

Leave a comment