等待多个任务的时间是否比第一个例外更多?

今天我的同事和我讨论了如何正确处理C#5.0 async方法中的exception,我们想知道是否同时等待多个任务也会观察到运行时未解包的exception。

请考虑以下代码段:

 async Task ExceptionMethodAsync() { await Task.Yield(); throw new Exception(); } async Task CallingMethod() { try { var a = ExceptionMethodAsync(); var b = ExceptionMethodAsync(); await Task.WhenAll(a, b); } catch(Exception ex) { // Catches the "first" exception thrown (whatever "first" means) } } 

现在第二项任务会发生什么? 两者都处于故障状态,但是现在观察到还是未观察到的第二个任务exception?

Task.WhenAll返回一个任务,就像所有任务一样, Exception属性包含一个组合所有exception的AggregateException

当您await这样的任务时,实际上只会抛出第一个exception。

…无论是因为子任务出错,还是因为像Task.WhenAlll这样的组合器,单个任务可能代表多个操作,而且多个操作可能有故障。 在这种情况下,并且目标是不丢失exception信息(这对于事后调试很重要),我们希望能够表示多个exception,因此对于包装器类型,我们选择了AggregateException。

…考虑到这一点,并再次选择总是抛出第一个或总是抛出一个聚合,为“等待”我们选择始终抛出第一个

来自.NET 4.5中的任务exception处理

您可以选择是否要使用await task;来处理第一个问题await task; (在大多数情况下为true)或使用task.Exception处理所有task.Exception (如下例所示),但在这两种情况下, ab都不会引发UnobservedTaskException

 var task = Task.WhenAll(a, b); try { await task; } catch { Trace.WriteLine(string.Join(", ", task.Exception.Flatten().InnerExceptions.Select(e => e.Message))); }