2010-09-11 69 views
12

http://msdn.microsoft.com/en-us/library/dd988458.aspx什么是TaskFactory.StartNew()中的“cancellationToken”用于?

UPD

所以,让我们讨论一下这篇文章,那么:http://msdn.microsoft.com/en-us/library/dd997396.aspx

我已经改变了代码一点:

static void Main() 
    { 

     var tokenSource2 = new CancellationTokenSource(); 
     CancellationToken ct = tokenSource2.Token; 

     var task = Task.Factory.StartNew(() => 
     { 

      // Were we already canceled? 
      ct.ThrowIfCancellationRequested(); 

      bool moreToDo = true; 
      Thread.Sleep(5000); 
      while (moreToDo) 
      { 

       // Poll on this property if you have to do 
       // other cleanup before throwing. 
       if (ct.IsCancellationRequested) 
       { 
        Console.WriteLine("exit"); 
        // Clean up here, then... 
        ct.ThrowIfCancellationRequested(); 
       } 

      } 
     }, tokenSource2.Token); // this parameter useless 

     Console.WriteLine("sleep"); 
     Thread.Sleep(2000); 
     Console.WriteLine("cancel"); 

     tokenSource2.Cancel(); 

     // Just continue on this thread, or Wait/WaitAll with try-catch: 
     try 
     { 
      task.Wait(); 
     } 
     catch (AggregateException e) 
     { 
      foreach (var v in e.InnerExceptions) 
      { 
       Console.WriteLine(e.Message + " " + v.Message); 
      } 
     } 

     Console.ReadKey(); 
    } 

UPD:嗯,这只改变了task.IsCanceled,这是imho无用,因为我仍然应该手动实施全部。

+0

请参阅[任务取消](http://msdn.microsoft.com/en-us/library/dd997396.aspx)。 – 2010-09-11 04:17:38

+2

我见过它。 “},tokenSource2.Token)” - 这个参数没有改变。要么我们有或没有这个令牌传递 - 我们将得到一个异常,因为'ct'由闭包处理。 – zerkms 2010-09-11 04:27:38

+1

太糟糕了,这个问题没有真正的答案,我也想知道这个论点的必要性......它现在看起来完全没有用处。 – 2011-09-15 21:30:35

回答

28

由于评论,我发布另一个答案。

考虑下面的代码:

var tokenSource = new CancellationTokenSource(); 
CancellationToken ct = tokenSource.Token; 

tokenSource.Cancel(); 

var task = Task.Factory.StartNew(() => 
{  
    // Were we already canceled? 
    ct.ThrowIfCancellationRequested(); 
    // do some processing 
}); 

即使调用tokenSource.Cancel()发出的任务实际上在开始之前,你还是会从分配线程池中的工作线程,所以你会浪费一定的系统资源。

但是,当您在Task.Factory.StartNew中指定了令牌参数时,该任务将立即取消,而不分配工作线程。

+2

这应该可能是被接受的答案 - 以上面的名义发布。一个问题 - 有没有办法获得传入的当前任务的取消标记?有点像Dispatcher.CurrentDispatcher的等价物? – BrainSlugs83 2013-12-12 23:39:20

+2

这难倒了相当长的一段时间。是否有任何MSDN文档证实了这一点? – 2014-07-08 06:49:54

+1

请参阅http://stackoverflow.com/a/3713113/2394945 – 2016-04-28 19:28:59

3

取消任务仍然是合作。你不希望线程在某些关键操作中被杀死。你需要检查它。

CancellationTokens比简单的结构好一些,比如ManualResetEvent用于信号关闭操作,因为您可以级联或组合它们,例如,您可以为整个应用程序关闭一个信号,并且您可以将其与一个用于取消特定任务。该任务只需查看一个CancellationToken,但您可以从CancellationTokenSource中取消它。

+0

那么,我如何在Work()中获得该标记参数? – zerkms 2010-09-11 04:33:05

+1

那么,你可以使用http://msdn.microsoft.com/en-us/library/dd780315.aspx传递它,但是当你开始实现你自己的'TaskFactory'并且想要具有级联取消标记等,然后它比简单的'ManualResetEvent'或类似的功能强大得多。 – 2010-09-11 04:56:16

+0

@zerkms:另请阅读MSDN上的[取消](http://msdn.microsoft.com/en-us/library/dd997364.aspx),其中提供了有关统一取消框架的更多高级视图。任务取消就是'Task'对象如何使用取消。如果您阅读了“大图”取消文章,那么效益应该变得更清晰。 – 2010-09-11 12:15:09