Created
July 1, 2014 01:36
-
-
Save ctigeek/2f67df6f1a3a68be3ceb to your computer and use it in GitHub Desktop.
ParallelTaskRunnerExtension - Running tasks in parallel, but limiting the concurrency.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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--; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.