Skip to content

Instantly share code, notes, and snippets.

@hallojoe
Last active December 14, 2019 17:00
Show Gist options
  • Save hallojoe/fb9b2b7fb471da43927452c0ecdacf41 to your computer and use it in GitHub Desktop.
Save hallojoe/fb9b2b7fb471da43927452c0ecdacf41 to your computer and use it in GitHub Desktop.
Executes a collection of functions, in parallel managed by a semaphore.
/// <summary>
/// Executes a list of functions, in parallel managed by a semaphore.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="values">The values to act on.</param>
/// <param name="maxDegreeOfParallelism">Maximum degree of parallelism when executing functions.</param>
/// <param name="fn">Function to call using value.</param>
/// <returns></returns>
public static async Task ManagedForEachAsync<T>(this IEnumerable<T> values, int maxDegreeOfParallelism, Func<T, Task> fn)
{
// initialize manager(semaphore)
var resourceManager = new SemaphoreSlim(maxDegreeOfParallelism, maxDegreeOfParallelism);
// list of tasks to throttle
var throttledTasks = new List<Task>();
// iterate values
foreach (var value in values)
{
// await resource available signal
await resourceManager.WaitAsync();
// add task to run
throttledTasks.Add(Task.Run(async () =>
{
// await finish task function
await fn(value).ContinueWith(res =>
{
// release resource
resourceManager.Release();
});
}));
}
// Wait for all tasks to complete.
await Task.WhenAll(throttledTasks.ToArray()).ContinueWith(x =>
{
// dispose resourceManager
resourceManager.Dispose();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment