Dan*_*bio 7 c# parallel-processing exception-handling async-await
问题
有几个任务是并行运行的,all,none或者其中任何一个都可能抛出异常.当所有任务完成后,必须报告所有可能发生的异常(通过日志,电子邮件,控制台输出......等等).
预期的行为
我可以通过linq和async lambdas构建所有任务,然后等待它们并行运行Task.WhenAll(tasks)
.然后我可以抓住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;
});
}
Run Code Online (Sandbox Code Playgroud)
产量
请注意,由于竞争条件,"我要投掷"消息的输出顺序可能会发生变化.
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
Run Code Online (Sandbox Code Playgroud)
Evk*_*Evk 13
这是因为await
"解包"聚合异常并且总是抛出第一个异常(如await文档中所述),即使等待Task.WhenAll
显然会导致多个错误.您可以访问聚合异常,例如:
var whenAll = Task.WhenAll(tasks);
try {
await whenAll;
}
catch {
// this is `AggregateException`
throw whenAll.Exception;
}
Run Code Online (Sandbox Code Playgroud)
或者你可以循环遍历任务并检查每个任务的状态和异常.
请注意,在修复之后,您还需要做一件事:
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;
});
}
Run Code Online (Sandbox Code Playgroud)
因为ThrowSeveralExceptionsAsync
包含的任务包含AggregateException
我们抛出,包裹在另一个内部AggregateException
.
归档时间: |
|
查看次数: |
1201 次 |
最近记录: |