【问题标题】:When does Task.Run(Action, CancellationToken) throw TaskCanceledException?Task.Run(Action, CancellationToken) 什么时候抛出 TaskCanceledException?
【发布时间】:2014-11-30 06:01:30
【问题描述】:

当任务被取消时,根据documentationTask.Run(Action, CancellationToken)抛出TaskCanceledException

Task.Run(Action, CancellationToken) 究竟什么时候抛出 TaskCanceledException?目前尚不清楚必须满足哪些条件才能引发此异常。

【问题讨论】:

  • 您是否检查了问题中链接到的页面上的示例?
  • @zerkms,我已经检查了这个例子。它表明 TaskCanceledException 是由 Task.Wait() 方法而不是由 Task.Run() 引发的。我试图了解在什么条件下 Task.Run() 会抛出 TaskCancelledException。

标签: c# .net task-parallel-library


【解决方案1】:

似乎有些混乱(文档可能具有误导性)。

调用Task.Run 方法将永远抛出TaskCanceledException(至少在当前实现中)。与ArgumentNullExceptionObjectDisposedException 不同,它们在“操作参数为空”和“与cancellationToken 关联的CancellationTokenSource 已释放”时同步抛出。分别。

Task.Run 但是返回一个Task 可以使用CancellationToken 参数取消(更多关于here 的取消)并使用await tasktask.Wait()task.Result 等等待它。会抛出TaskCanceledException(可能包裹在AggregateException中)

Task<int> task = null;
try
{
    task = Task.Run(() => 5, new CancellationToken(true));
}
catch (TaskCanceledException)
{
    Console.WriteLine("Unreachable code");
}

try
{
    int result = await task;
}
catch (TaskCanceledException)
{
    Console.WriteLine("Awaiting a canceled task");
}

如果文档有两节可能的例外情况可能会更清楚:

  1. “常规”同步异常(例如 ArgumentNullExceptionObjectDisposedException
  2. “async”异步异常,只能通过等待返回的任务来抛出(例如TaskCanceledException

【讨论】:

  • @l3arnon,这听起来很合理。您是如何发现调用 Task.Run 方法永远不会抛出 TaskCanceledException 的?
  • @Alex 好吧,经验。但是,如果您愿意进入兔子洞,您可以查看 source code for Task.Run 并仅查看同步抛出的其他异常。
  • 文档炸了。
  • "Task.Run 但是返回一个可以使用 CancellationToken 参数取消的任务(这里有更多关于取消的内容)并使用 await task、task.Wait()、task 等待它。结果等会抛出一个 TaskCanceledException" ——这是非常具有误导性的。只需源“取消”而不显式地抛出用户代码,它永远不会导致await task 抛出TaskCanceledException,除非在任务开始之前取消;至于WaitWait() 取消后不会抛出,但Wait(token) 会。我没试过Result,所以不评论。
  • @Tomingsun Wait(和 Result)在取消的任务上抛出一个 TaskCanceledException 包裹在通常的聚合异常中。至于合作取消……你是对的。我不认为这是OP的问题。不仅邀请您编辑答案并对其进行扩展。
【解决方案2】:

阅读Cancellation in Managed Thread

只有请求对象才能发出取消请求,每个监听器负责注意到请求并及时响应。

然后继续:

取消是合作的,不会强加给监听器。监听器决定如何优雅地终止以响应取消请求。

您需要确保您正在收听CancellationToken.IsCancelledRequested 或抛出异常CancellationToken.ThrowIfCancelltionRequested您的有责任取消和await 观察取消异常的操作。

【讨论】:

    猜你喜欢
    • 2011-03-22
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多