Skip to content

Instantly share code, notes, and snippets.

@jhoerr
Created August 13, 2015 22:11
Show Gist options
  • Save jhoerr/8daf75c3f517bba2bb52 to your computer and use it in GitHub Desktop.
Save jhoerr/8daf75c3f517bba2bb52 to your computer and use it in GitHub Desktop.
public static class ConcurrentCollectionExtensions
{
private const int MaxDegreeOfConcurrency = 10;
/// <summary>
/// Concurrently perform a task on each member of a collection
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection">The collection upon which each task should be performed</param>
/// <param name="concurrentTask">The task to perform</param>
/// <param name="maxDegreeOfConcurrency">The maximum number of concurrent operations</param>
/// <returns></returns>
public static async Task ConcurrentForEach<T>(this IEnumerable<T> collection, Func<T, Task> concurrentTask, int maxDegreeOfConcurrency = MaxDegreeOfConcurrency)
{
var semaphore = new SemaphoreSlim(maxDegreeOfConcurrency);
var tasks = collection.Select(async student =>
{
using (await semaphore.TakeAsync())
await concurrentTask(student);
});
await Task.WhenAll(tasks);
}
}
public static class SemaphoreSlimExtensions
{
public static async Task<IDisposable> TakeAsync(this SemaphoreSlim semaphore)
{
await semaphore.WaitAsync().ConfigureAwait(false);
return new SemaphoreSlimKey(semaphore);
}
private sealed class SemaphoreSlimKey : IDisposable
{
private readonly SemaphoreSlim _semaphore;
public SemaphoreSlimKey(SemaphoreSlim semaphore) { _semaphore = semaphore; }
void IDisposable.Dispose() { _semaphore.Release(); }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment