繁体   English   中英

正确处理任务取消的一般方法

[英]General approach to handle Task cancellation correctly

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

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 out out并且从不使用Wait/Result 因此,她不喜欢另外观察AggregateException进行取消的想法。 但是,我的观点是一些标准的基于Task的BCL API仍然可以使用AggregateException包装OperationCanceledException ,例如因为它们仍然可能在内部访问Task.Result

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

但是,我的观点是一些标准的基于任务的BCL API仍然可以使用AggregateException包装OperationCanceledException,例如因为它们仍然可能在内部访问Task.Result。

不,他们不会这样做。

我们应该担心同时处理OperationCanceledException和AggregateException以正确观察取消吗?

我会说不。 这是当然, 可能是一个AggregateException可以包含OperationCanceledException ,但它也可以包含other particular exceptions一样容易。

只要您遵循异步最佳实践(即,没有异步同步或同步异步),您就不必担心这一点。

嗯,这绝对是技术上可行的,这个代码很容易验证:

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中的任何方法都不太可能这样做,如果它确实存在比异常处理更大的问题,因为您执行异步过度同步。 我会更担心你自己的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM