肯定 System.Threading.Tasks.Task 构造师占用 CancellationToken 作为参数:

CancellationTokenSource source = new CancellationTokenSource();
Task t = new Task (/* method */, source.Token);

令我感到困惑的是,没有办法 里面 实际获取令牌的方法主体(例如,没有什么比 Task.CurrentTask.CancellationToken)。必须通过其他一些机制来提供令牌,例如状态对象或在lambda中捕获。

那么,在构造函数中提供取消令牌的目的是什么?

有帮助吗?

解决方案

将此令牌传递到任务构造函数中,将其与此任务相关联。

引用 斯蒂芬·图布(Stephen Toub)的回答:

这有两个主要好处:

  1. 如果令牌在任务开始执行之前已请求取消,则任务将无法执行。而不是过渡到 Running, ,它会立即过渡到 Canceled. 。如果无论如何在运行时都会被取消,则可以避免运行任务的成本。
  2. 如果任务的主体还在监视取消令牌并抛出 OperationCanceledException 包含该令牌(这是什么 ThrowIfCancellationRequested ),然后任务看到 OperationCanceledException, ,它检查了是否 OperationCanceledException的令牌与任务的令牌匹配。如果确实如此,则该例外被视为合作取消的确认,并且任务过渡到已取消状态(而不是故障状态)。

其他提示

构造函数使用令牌进行内部取消处理。如果您的代码希望访问令牌,则负责将其传递给自己。我强烈建议您阅读 与Microsoft .NET书籍的平行编程在Codeplex上.

本书中CT的使用示例:

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

Task myTask = Task.Factory.StartNew(() =>
{
    for (...)
    {
        token.ThrowIfCancellationRequested();

        // Body of for loop.
    }
}, token);

// ... elsewhere ...
cts.Cancel();

取消并不是许多人想像的情况。有关MSDN的博客文章中解释了一些微妙之处:

例如:

在某些情况下,在并行扩展和其他系统中,有必要唤醒被阻止的方法,原因是用户明确取消的原因。例如,如果一个线程在blockingCollection.take()上被阻止,因为该集合为空并且另一个线程随后呼叫blockingCollection.completeadding(),则第一个调用应唤醒并投掷InvalidoperationException以表示不正确的用法。

http://blogs.msdn.com/b/pfxteam/archive/2009/06/22/9791840.aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top