我正在进行代码审查,并且我担心这种模式,贯穿所有代码:

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.WaitTask.Result会抛出这样的AggregateException,而不是OperationCanceledException。该代码的作者向我保证,她从内而外仅使用async/await,而从不使用Wait/Result。因此,她不喜欢额外观察AggregateException取消的想法。但是,我的意思是,某些基于Task的标准BCL API仍可以用OperationCanceledException包装AggregateException,例如因为他们仍然可能在内部访问Task.Result

是否有意义?我们应该担心同时处理OperationCanceledExceptionAggregateException以正确观察取消吗?

最佳答案

好吧,在技术上绝对是可能的,这很容易通过以下代码进行验证:

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中的任何方法都不太可能做到这一点,而且如果这样做的话,与异步处理相比,您会遇到比异常处理更大的问题。
我会更担心自己的代码。

10-04 23:03