Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正确处理任务取消的一般方法_C#_.net_Task Parallel Library_Async Await_Cancellation - Fatal编程技术网

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,这听起来很合理,我会在一段时间内接受它作为一个答案。