Problem
Several tasks are run in parallel, and all, none, or any of them might throw exceptions. When all the tasks have finalized, all the exceptions that might have happened must be reported (via log, email, console output.... whatever).
Expected behavior
I can build all the tasks via linq with async lambdas, and then await for them running in parallel with Task.WhenAll(tasks)
. Then I can catch an AggregateException
and report each of the individual inner exceptions.
Actual behavior
An AggregateException
is thrown, but it contains just one inner exception, whatever number of individual exceptions have been thrown.
Minimal complete verifiable example
static void Main(string[] args)
{
try
{
ThrowSeveralExceptionsAsync(5).Wait();
}
catch (AggregateException ex)
{
ex.Handle(innerEx =>
{
Console.WriteLine($"\"{innerEx.Message}\" was thrown");
return true;
});
}
Console.ReadLine();
}
private static async Task ThrowSeveralExceptionsAsync(int nExceptions)
{
var tasks = Enumerable.Range(0, nExceptions)
.Select(async n =>
{
await ThrowAsync(new Exception($"Exception #{n}"));
});
await Task.WhenAll(tasks);
}
private static async Task ThrowAsync(Exception ex)
{
await Task.Run(() => {
Console.WriteLine($"I am going to throw \"{ex.Message}\"");
throw ex;
});
}
Output
Note that the output order of the "I am going to throw" messages might change, due to race conditions.
I am going to throw "Exception #0"
I am going to throw "Exception #1"
I am going to throw "Exception #2"
I am going to throw "Exception #3"
I am going to throw "Exception #4"
"Exception #0" was thrown