How to make Task.WaitAll() to break if any exception happened?

The following should do it without altering the code of the original tasks (untested):

static bool WaitAll(Task[] tasks, int timeout, CancellationToken token)
{
    var cts = CancellationTokenSource.CreateLinkedTokenSource(token);

    var proxyTasks = tasks.Select(task => 
        task.ContinueWith(t => {
            if (t.IsFaulted) cts.Cancel();
            return t; 
        }, 
        cts.Token, 
        TaskContinuationOptions.ExecuteSynchronously, 
        TaskScheduler.Current).Unwrap());

    return Task.WaitAll(proxyTasks.ToArray(), timeout, cts.Token);
}

Note it only tracks faulted tasks (those which threw). If you need to track cancelled tasks as well, make this change:

if (t.IsFaulted || t.IsCancelled) cts.Cancel();

Updated, waiting on the task proxies is redundant here, as pointed out by @svick in the comments. He proposes an improved version: https://gist.github.com/svick/9992598.

Leave a Comment

tech