【问题标题】:What is the use of passing CancellationToken to Task Class constructor?将 CancellationToken 传递给 Task Class 构造函数有什么用?
【发布时间】:2012-06-06 14:07:56
【问题描述】:

这是一个示例代码,它创建了一个模拟长时间运行的进程的新任务。任务本身并没有太多内容,只关注取消功能。我正在使用取消令牌来取消任务,代码对我来说很好。

CancellationTokenSource CTS = new CancellationTokenSource();

Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
          Thread.Sleep(5000);
       }
       else { Console.WriteLine("Thread Cancelled");break; }
   }
   return true;

}, CTS.Token, TaskCreationOptions.None);

PTask.Start();
Console.WriteLine("Hit Enter to cancel the Secondary thread you have started");
Console.ReadLine();
CTS.Cancel();
System.Console.WriteLine(PTask.Result);

但我无法理解的一件事是传递给Task 构造函数的令牌参数(CTS.Token)。传递参数的实际用途是什么,即使没有将令牌传递给构造函数,我实际上也可以取消任务。

下面是一个稍加修改的版本,无需令牌参数即可工作。

CancellationTokenSource CTS = new CancellationTokenSource();
Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
           Thread.Sleep(5000);
       }
       else
       {
           Console.WriteLine("Thread Cancelled");
           break;
       }
};

【问题讨论】:

标签: c# .net multithreading cancellation-token


【解决方案1】:

更新: 以下msdn 问题描述了原因:

将令牌传递到 StartNew 将令牌与任务相关联。 这有两个主要好处:

  1. 如果令牌有取消 在任务开始执行之前请求,任务不会 执行。而不是过渡到跑步,它会立即 过渡到取消。这避免了运行任务的成本,如果 无论如何,它只会在运行时被取消。

  2. 如果身体 任务也在监视取消令牌并抛出一个 OperationCanceledException 包含该令牌(这是什么 ThrowIfCancellationRequested 确实),然后当任务看到该 OCE 时, 它检查 OCE 的令牌是否与任务的令牌匹配。如果它 确实,该例外被视为对合作的承认 取消和任务转换到取消状态(而不是 比故障状态)。

【讨论】:

  • 你是说使用主线程令牌的iscancelrequest检查是不安全的。
  • 我看不出将令牌传递给构造函数的任何其他原因,但如果您问我是否 100% 确定;不是。
  • 我更新了,其实这和线程安全无关。
  • 第 2 点似乎无效。 Task.Run(async () =&gt; { throw new OperationCanceledException(); }, new CancellationToken(false)).ContinueWith(tsk =&gt; Console.WriteLine(tsk.Status)) 返回 Canceled,而不是 Faulted。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2015-09-24
相关资源
最近更新 更多