2010-09-11 36 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

相關問題