在Task.WhenAll
调用中导致多个异常时,一旦您通过多于一层的等待等待它,看起来只有一个异常被吸收到任务中。我的印象是该Task.Exception.InnerExceptions
属性将包含所有发生的异常,但在某些情况下,它们似乎只有一个。
例如,此示例代码创建多个引发异常的任务,然后在它们上等待一个 Task.WhenAll,然后写入控制台它能够捕获的异常:
class Program
{
static async Task Main(string[] args)
{
var task = CauseMultipleExceptionsAsync();
// Delaying until all the Exceptions have been thrown, ensuring it isn't just a weird race condition happening behind the scenes
await Task.Delay(5000);
try
{
await task;
}
catch(AggregateException e)
{
// This does not get hit
Console.WriteLine($"AggregateException caught: Found {e.InnerExceptions.Count} inner exception(s)");
}
catch(Exception e)
{
Console.WriteLine($"Caught other Exception {e.Message}");
Console.WriteLine($"task.Exception.InnerExceptions contains {task.Exception.InnerExceptions.Count} exception(s)");
foreach (var exception in task.Exception.InnerExceptions)
{
Console.WriteLine($"Inner exception {exception.GetType()}, message: {exception.Message}");
}
}
}
static async Task CauseMultipleExceptionsAsync()
{
var tasks = new List<Task>()
{
CauseExceptionAsync("A"),
CauseExceptionAsync("B"),
CauseExceptionAsync("C"),
};
await Task.WhenAll(tasks);
}
static async Task CauseExceptionAsync(string message)
{
await Task.Delay(1000);
Console.WriteLine($"Throwing exception {message}");
throw new Exception(message);
}
}
我期望这要么进入catch(AggregateException e)
子句,要么至少有三个内部异常task.Exception.InnerExceptions
- 引发一个异常的实际情况是,只有一个异常在task.Exception.InnerExceptions
:
Throwing exception B
Throwing exception A
Throwing exception C
Caught other Exception A
task.Exception.InnerExceptions contains 1 exception(s)
Inner exception System.Exception, message: A
更奇怪的是,这种行为会根据您是否等待Task.WhenAll
调用而改变CauseMultipleExceptionsAsync
——如果您直接返回任务而不是等待它,那么所有三个异常都会出现在task.Exception.InnerException
. 例如,替换CauseMultipleExceptionsAsync
为:
static Task CauseMultipleExceptionsAsync()
{
var tasks = new List<Task>()
{
CauseExceptionAsync("A"),
CauseExceptionAsync("B"),
CauseExceptionAsync("C"),
};
return Task.WhenAll(tasks);
}
给出这个结果,task.Exception.InnerExceptions 中包含所有三个异常:
Throwing exception C
Throwing exception A
Throwing exception B
Caught other Exception A
task.Exception.InnerExceptions contains 3 exception(s)
Inner exception System.Exception, message: A
Inner exception System.Exception, message: B
Inner exception System.Exception, message: C
我对此感到很困惑 - 在最初的示例中异常 B 和 C 去了哪里?如果 Task.Exception 不包含有关它们的任何信息,您将如何再次找到它们?为什么 awaiting insideCauseMultipleExceptionsAsync
隐藏了这些异常,而Task.WhenAll
直接返回却没有?
如果它有所作为,我可以在 .Net Framework 4.5.2 和 .Net Core 2.1 中复制上述内容。