public static async Task Worker(FunctionToGetWorkItem getWorkItem, Action <Exception> callOnException, int maxParallel) { Task[] tasksInProgress = new Task[maxParallel]; int numTasksInProgress = 0; while (true) { Task newTask; if (!getWorkItem(out newTask)) { // There are no more tasks to perform. Wait until the last one is completed. if (numTasksInProgress > 0) { await Task.WhenAll(tasksInProgress.Take(numTasksInProgress)); } return; } if (newTask.IsCompleted || newTask.IsCanceled) { continue; } if (newTask.IsFaulted) { callOnException(newTask.Exception); continue; } // The task could not complete immediately, is still in progress, and needs to be awaited... if (numTasksInProgress > 0) { RemoveCompletedTasks(tasksInProgress, ref numTasksInProgress, callOnException); if (numTasksInProgress >= tasksInProgress.Length) { await Task.WhenAny(tasksInProgress); RemoveCompletedTasks(tasksInProgress, ref numTasksInProgress, callOnException); } } // Now add the new task tasksInProgress[numTasksInProgress++] = newTask; } }
public static async Task Worker(FunctionToGetWorkItem getWorkItem, Action <Exception> callOnException, int maxParallel) { Task[] tasksInProgress = new Task[maxParallel]; int numTasksInProgress = 0; while (true) { Task newTask; if (!getWorkItem(out newTask)) { if (numTasksInProgress > 0) { await Task.WhenAll(tasksInProgress.Take(numTasksInProgress)); } return; } if (newTask.IsCompleted || newTask.IsCanceled) { continue; } if (newTask.IsFaulted) { callOnException(newTask.Exception); continue; } if (numTasksInProgress > 0) { RemoveCompletedTasks(tasksInProgress, ref numTasksInProgress, callOnException); if (numTasksInProgress >= tasksInProgress.Length) { await Task.WhenAny(tasksInProgress); RemoveCompletedTasks(tasksInProgress, ref numTasksInProgress, callOnException); } } tasksInProgress[numTasksInProgress++] = newTask; } }