我正在进行代码审查,并且我担心这种模式,贯穿所有代码:
try
{
await DoSomethingAsync();
await DoSomethingElseAsync();
// and so on...
}
catch (OperationCanceledException)
{
// all good, user cancelled
// log and return
return;
}
// handle other particular exceptions
// ...
catch (Exception ex)
{
// fatal error, alert the user
FatalErrorMessage(ex);
}
我关心的部分是处理
OperationCanceledException
。该代码是否还应处理AggregateException
并检查是否唯一的内部异常是OperationCanceledException
?我知道
Task.Wait
或Task.Result
会抛出这样的AggregateException
,而不是OperationCanceledException
。该代码的作者向我保证,她从内而外仅使用async/await
,而从不使用Wait/Result
。因此,她不喜欢额外观察AggregateException
取消的想法。但是,我的意思是,某些基于Task
的标准BCL API仍可以用OperationCanceledException
包装AggregateException
,例如因为他们仍然可能在内部访问Task.Result
。是否有意义?我们应该担心同时处理
OperationCanceledException
和AggregateException
以正确观察取消吗? 最佳答案
好吧,在技术上绝对是可能的,这很容易通过以下代码进行验证:
static void Main()
{
Test().Wait();
}
static async Task Test()
{
try
{
await ThrowAggregate();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static async Task ThrowAggregate()
{
ThrowException().Wait();
}
static async Task ThrowException()
{
throw new OperationCanceledException();
}
ThrowAggregate
将AggregateException存储在返回的任务中,因此等待它仍会引发AggregateException
。因此,如果您想勤奋工作,也需要抓住AggregateException
。但是,BCL中的任何方法都不太可能做到这一点,而且如果这样做的话,与异步处理相比,您会遇到比异常处理更大的问题。
我会更担心自己的代码。