等待多个任务的时间是否比第一个例外更多?
今天我的同事和我讨论了如何正确处理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
(如下例所示),但在这两种情况下, a
和b
都不会引发UnobservedTaskException
。
var task = Task.WhenAll(a, b); try { await task; } catch { Trace.WriteLine(string.Join(", ", task.Exception.Flatten().InnerExceptions.Select(e => e.Message))); }