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

编程入门 行业动态 更新时间:2024-10-26 02:33:42
为什么Task.WhenAll抛出TaskCanceledException和Task.WhenAny不在同一个测试用例中(Why Task.WhenAll throws TaskCanceledException and Task.WhenAny doesnt in the same test case)

我运行这个代码:

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); }

我明白了

await WhenAll System.Threading.Tasks.TaskCanceledException: A task was canceled.

我认为它会执行,因为某些任务已经处于取消状态。 为什么Task.WhenAll方法打破正常流程并在取消子任务的情况下抛出异常? Whant受益于这种行为?

然后,我尝试Task.WhenAny方法:

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不会在相同情况下抛出异常? 我期望这两种方法都应该以相同的方式处理取消的任务:或者抛出异常。

I run this code:

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); }

And I get

await WhenAll System.Threading.Tasks.TaskCanceledException: A task was canceled.

I assume that it trows because some task is already in cancelled state. Why does Task.WhenAll method breaks normal flow and throws the exception in case of cancelled child tasks? Whant is benefit from this behavior?

Then, I try the method Task.WhenAny:

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); }

and it doesnt throw exceptions.

The second question is why Task.WhenAny does not throw exceptions in the same case? I expect that both methods should handle cancelled tasks the same way: either throw exceptions or not.

最满意答案

Task.WhenAny旨在完成任何一个任务完成时,完成包括失败。 当其中一项任务可能失败时,我发现它非常有用。 例如:

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只在所有任务完成时(无论是否成功)完成。 它可以抛出异常,因为没有任何东西可以处理,计算完成。

Task.WhenAny is designed to complete whenever one of the tasks completes, where completion includes failure. I actually find it most useful when one of the tasks might fail. For instance:

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) { ... }

Here I only need one of the tasks to complete (hence, the WhenAny). In which case I would like to cancel the other tasks as well. Then I call WhenAll to wait for the other task to respect the cancellation request, and also propagate an exception if it occurred.

In other words, Task.WhenAny is designed to let you do something while other tasks are still running, and it is useful for it not to throw exceptions in order to let you do whatever you want with the other tasks. Task.WhenAll only completes when all the tasks complete (either successfully or not). It can throw the exception because there is nothing left for you to handle, the computation is complete.

更多推荐

本文发布于:2023-08-01 14:20:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1359334.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:抛出   测试   TaskCanceledException   WhenAny   WhenAll

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!