【发布时间】:2018-07-19 02:56:51
【问题描述】:
问题
多个任务并行运行,所有任务、无任务或其中任何任务都可能引发异常。当所有任务都完成后,必须报告所有可能发生的异常(通过日志、电子邮件、控制台输出......无论如何)。
预期行为
我可以通过带有异步 lambda 的 linq 构建所有任务,然后等待它们与 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;
});
}
输出
请注意,由于竞争条件,“我要扔”消息的输出顺序可能会发生变化。
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
【问题讨论】:
-
排序相关,你可以让你的入口点异步,只需添加
static async Task Main -
@BradM 如果你这样做,它会完全中断(可能是由于
async Main在内部的工作方式) -
有趣,不知道这些。不过,这对于另一个问题来说很重要。
标签: c# exception-handling parallel-processing async-await