Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
ParallelTaskRunnerExtension - Running tasks in parallel, but limiting the concurrency.
public static class ParallelTaskRunnerExtension
{
public static void RunTasks(this IEnumerable<Task> tasks, int maxConcurrency, Action<Task> taskComplete = null)
{
if (maxConcurrency <= 0) throw new ArgumentException("maxConcurrency must be more than 0.");
int taskCount = 0;
int nextIndex = 0;
var currentTasks = new Task[maxConcurrency];
foreach (var task in tasks)
{
currentTasks[nextIndex] = task;
taskCount++;
if (taskCount == maxConcurrency)
{
nextIndex = Task.WaitAny(currentTasks);
if (taskComplete != null)
{
taskComplete(currentTasks[nextIndex]);
}
currentTasks[nextIndex] = null;
taskCount--;
}
else
{
nextIndex++;
}
}
while (taskCount > 0)
{
currentTasks = currentTasks.Where(t => t != null).ToArray();
nextIndex = Task.WaitAny(currentTasks);
if (taskComplete != null)
{
taskComplete(currentTasks[nextIndex]);
}
currentTasks[nextIndex] = null;
taskCount--;
}
}
public static void RunTasks<T>(this IEnumerable<Task<T>> tasks, int maxConcurrency, Action<Task<T>> taskComplete = null)
{
if (maxConcurrency <= 0) throw new ArgumentException("maxConcurrency must be more than 0.");
int taskCount = 0;
int nextIndex = 0;
var currentTasks = new Task<T>[maxConcurrency];
foreach (var task in tasks)
{
currentTasks[nextIndex] = task;
taskCount++;
if (taskCount == maxConcurrency)
{
nextIndex = Task.WaitAny(currentTasks);
if (taskComplete != null)
{
taskComplete(currentTasks[nextIndex]);
}
currentTasks[nextIndex] = null;
taskCount--;
}
else
{
nextIndex++;
}
}
while (taskCount > 0)
{
currentTasks = currentTasks.Where(t => t != null).ToArray();
nextIndex = Task.WaitAny(currentTasks);
if (taskComplete != null)
{
taskComplete(currentTasks[nextIndex]);
}
currentTasks[nextIndex] = null;
taskCount--;
}
}
}

I just wanted to say Thank You for this code and the outstanding article you wrote which explains your process and choices. I was able to adapt this to a prototype I am building and it works like a champion. I appreciate that you took the time to share this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment