C# 正确处理任务取消的一般方法
我正在做一个代码审查,我很关心这个模式,从代码中可以看到:C# 正确处理任务取消的一般方法,c#,.net,task-parallel-library,async-await,cancellation,C#,.net,Task Parallel Library,Async Await,Cancellation,我正在做一个代码审查,我很关心这个模式,从代码中可以看到: try { await DoSomethingAsync(); await DoSomethingElseAsync(); // and so on... } catch (OperationCanceledException) { // all good, user cancelled // log and return return; } // handle other particu
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);
}
我关心的部分是处理操作取消异常
。此代码是否也应该处理聚合异常
并检查唯一的内部异常是否为操作取消异常
我知道Task.Wait
或Task.Result
会像那样抛出aggregateeexception
,而不是OperationCanceledException
。代码的作者向我保证,她只从内到外使用async/await
,从不使用Wait/Result
。因此,她不喜欢额外观察aggregateeexception
进行取消的想法。然而,我的观点是,一些基于标准的任务
的BCL API仍然可以使用聚合异常
包装操作取消异常
,例如,因为它们仍然可能在内部访问任务.结果
这有意义吗?我们是否应该同时处理
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
。因此,如果你想勤奋,你也需要抓住aggregateeexception
然而,BCL中的任何方法都不太可能做到这一点,如果真的做到了,那么您的问题比异常处理更大,因为您在同步上执行异步。
我会更担心你自己的代码
然而,我的观点是,一些基于任务的标准BCL API仍然可以将OperationCanceledException包装为AggregateException,例如,因为它们仍然可以在内部访问Task.Result
不,他们不会那样做的
我们是否应该同时处理OperationCanceledException和AggregateException以正确观察取消情况
我想说不。当然,aggregateeexception
可能包含OperationCanceledException
,但它也可能包含其他特定异常
只要您遵循异步最佳实践(即,没有异步过同步或同步过异步),那么您就不必担心这一点。谢谢@arnon,这听起来很合理,我会在一段时间内接受它作为一个答案。