In this code:
private async void button1_Click(object sender, EventArgs e) {
try {
await Task.WhenAll(DoLongThingAsyncEx1(), DoLongThingAsyncEx2(
Just thought I'd expand on @Richiban's answer to say that you can also handle the AggregateException in the catch block by referencing it from the task. E.g:
async Task Main()
{
var task = Task.WhenAll(A(), B());
try
{
var results = await task;
Console.WriteLine(results);
}
catch (Exception ex)
{
// This doesn't fire until both tasks
// are complete. I.e. so after 10 seconds
// as per the second delay
// The ex in this instance is the first
// exception thrown, i.e. "A".
var firstExceptionThrown = ex;
// This aggregate contains both "A" and "B".
var aggregateException = task.Exception;
}
}
public async Task A()
{
await Task.Delay(100);
throw new Exception("A");
}
public async Task B()
{
// Extra delay to make it clear that the await
// waits for all tasks to complete, including
// waiting for this exception.
await Task.Delay(10000);
throw new Exception("B");
}