25

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

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

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

下面是一个稍微修改过的版本,它在没有 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;
       }
};
4

1 回答 1

41

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

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

  1. 如果令牌在任务开始执行之前请求取消,任务将不会执行。它不会转换为 Running,而是立即转换为 Canceled。这避免了运行任务的成本,如果它只是在运行时被取消的话。

  2. 如果任务的主体也在监视取消令牌并抛出包含该令牌的 OperationCanceledException(这是什么 ThrowIfCancellationRequested),那么当任务看到该 OCE 时,它会检查 OCE 的令牌是否与任务的令牌匹配。如果是这样,则该异常被视为对合作取消的确认,并且任务转换到 Canceled 状态(而不是 Faulted 状态)。

于 2012-06-01T10:30:03.530 回答