[英]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.Wait
或Task.Result
会抛出类似的AggregateException
,而不是OperationCanceledException
。 代码的作者向我保证她只使用async/await
out out并且从不使用Wait/Result
。 因此,她不喜欢另外观察AggregateException
进行取消的想法。 但是,我的观点是一些标准的基于Task
的BCL API仍然可以使用AggregateException
包装OperationCanceledException
,例如因为它们仍然可能在内部访问Task.Result
。
是否有意义? 我们是否应该担心处理OperationCanceledException
和AggregateException
以正确观察取消?
但是,我的观点是一些标准的基于任务的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.