Matias Cicero Matias Cicero - 2 months ago 13
C# Question

Is there a callback for when a task is completed in Task.WhenAll

Suppose I have the following:

IEnumerable<Task<TimeSpan>> tasks = //...
TimeSpan[] results = await Task.WhenAll(tasks);
// Handle results


By the time I can handle the results all the task must have finished.

Is there a way to handle each result on demand?

Like registering a delegate / callback that will get executed when a task is completed:

IEnumerable<Task<TimeSpan>> tasks = //...
await Task.WhenAll(tasks, result =>
{
// A task has finished. This will get executed.
// result is of type TimeSpan
});

Answer

Is there a way to handle each result on demand?

Yes, you use WhenAny instead of WhenAll... or call ContinueWith on each task.

For example, for the WhenAny approach:

ISet<Task<TimeSpan>> tasks = new HashSet<Task<TimeSpan>>(...);
while (tasks.Count != 0)
{
    var task = await Task.WhenAny(tasks);
    // Use task here
    tasks.Remove(task);
}

There's another option you could use, where you transform the original sequence of tasks into a sequence of tasks which completes in order, but giving the same results. Details are in this blog post, but the result is that you can use:

foreach (var task in tasks.InCompletionOrder())
{
    var result = await task;
    // Use the result
}