首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Task.WhenAll抛出TaskCanceledException和Task.WhenAny不在同一个测试用例中

为什么Task.WhenAll抛出TaskCanceledException和Task.WhenAny不在同一个测试用例中
EN

Stack Overflow用户
提问于 2013-08-13 11:57:31
回答 2查看 5.6K关注 0票数 5

我运行以下代码:

代码语言:javascript
复制
var cancellation = new CancellationTokenSource();
var cancelledTask1 = .....;//starting new long-running task that accepts cancellation.Token
var cancelledTask2 = .....;//starting new long-running task that accepts cancellation.Token

//then I request cancellation
cancellation.Cancel();
//some task gets cancelled before code below executes
try
{
    //wait for completion (some task is already in cancelled state)
    await Task.WhenAll(cancelledTask1, cancelledTask2);
}
catch (OperationCanceledException e)
{
    Logger.Debug("await WhenAll", e);
}

我得到了

代码语言:javascript
复制
await WhenAll System.Threading.Tasks.TaskCanceledException: A task was canceled.

我认为这是因为某些任务已经处于取消状态。为什么Task.WhenAll方法破坏正常流并在取消子任务的情况下抛出异常?这种行为有什么好处?

然后,我尝试了Task.WhenAny方法。

代码语言:javascript
复制
var cancellation = new CancellationTokenSource();
var cancelledTask3 = .....;//starting new long-running task that accepts cancellation.Token

//then I request cancellation
cancellation.Cancel();
//the task gets cancelled before code below executes
try
{
    //wait for completion (the task is already in cancelled state)
    await Task.WhenAny(cancelledTask3);
}
catch (OperationCanceledException e)
{
    Logger.Debug("await WhenAny", e);
}

也不会抛出异常。

第二个问题是:为什么Task.WhenAny在同一种情况下不抛出异常?我希望这两种方法都应该以同样的方式处理取消的任务:抛出异常还是不抛出异常。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-13 13:27:33

Task.WhenAny的设计是为了在其中一个任务完成时完成,其中完成包括失败。实际上,当其中一项任务可能失败时,我发现它非常有用。例如:

代码语言:javascript
复制
try
{
   await Task.WhenAny(task1,task2);
   cancellationToken.Cancel(); //cancel all tasks
   await Task.WhenAll(task1,task2); //wait for both tasks to respect the cancellation
}
catch (Exception x)
{
...
}

在这里,我只需要完成一项任务(因此,WhenAny)。在这种情况下,我也想取消其他任务。然后,我调用WhenAll以等待其他任务尊重取消请求,并在发生异常时传播异常。

换句话说,Task.WhenAny的目的是让您在其他任务仍在运行时做一些事情,并且它不抛出异常以便让您对其他任务做任何事情是很有用的。只有当所有任务完成时(成功与否),Task.WhenAll才能完成。它可以抛出异常,因为您没有什么要处理的了,计算已经完成。

票数 7
EN

Stack Overflow用户

发布于 2017-07-21 23:22:56

Task.WhenAny返回一个Task<Task>,而Task.WhenAll返回一个Task。无论第一个已完成/取消/错误任务的状态如何,外部任务都成功完成。内部任务是第一个已取消的任务。因此,必须等待内部和外部任务才能抛出OperationCanceledException

例如:

代码语言:javascript
复制
await await Task.WhenAny(cancelledTask3);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18208508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档