c# – 处理来自异步并行任务的多个异常
发布时间:2020-12-15 18:08:21 所属栏目:百科 来源:网络整理
导读:问题 有几个任务是并行运行的,all,none或者其中任何一个都可能抛出异常.当所有任务完成后,必须报告所有可能发生的异常(通过日志,电子邮件,控制台输出……等等). 预期的行为 我可以使用asq lambdas通过linq构建所有任务,然后等待它们与Task.WhenAll(任务)并行
问题
有几个任务是并行运行的,all,none或者其中任何一个都可能抛出异常.当所有任务完成后,必须报告所有可能发生的异常(通过日志,电子邮件,控制台输出……等等). 预期的行为 我可以使用asq lambdas通过linq构建所有任务,然后等待它们与Task.WhenAll(任务)并行运行.然后我可以捕获AggregateException并报告每个单独的内部异常. 实际行为 抛出了AggregateException,但它只包含一个内部异常,无论抛出多少个别异常. 最小的完整可验证的例子 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; }); } 产量 请注意,由于竞争条件,“我要投掷”消息的输出顺序可能会发生变化. 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 解决方法
那是因为等待“解包”聚合异常并且总是抛出第一个异常(如
await的文档中所述),即使等待Task.WhenAll显然会导致多个错误.您可以访问聚合异常,例如:
var whenAll = Task.WhenAll(tasks); try { await whenAll; } catch { // this is `AggregateException` throw whenAll.Exception; } 或者你可以循环遍历任务并检查每个任务的状态和异常. 请注意,在修复之后,您还需要做一件事: try { ThrowSeveralExceptionsAsync(5).Wait(); } catch (AggregateException ex) { // flatten,unwrapping all inner aggregate exceptions ex.Flatten().Handle(innerEx => { Console.WriteLine($""{innerEx.Message}" was thrown"); return true; }); } 因为ThrowSeveralExceptionsAsync返回的任务包含我们抛出的AggregateException,包含在另一个AggregateException中. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
热点阅读