2016-07-17 119 views
0

另一種方式我有取消任務

class Program 
{ 
    private static void MyTask(object obj) 
    { 
     var cancellationToken = (CancellationToken) obj; 
     if(cancellationToken.IsCancellationRequested) 
      cancellationToken.ThrowIfCancellationRequested(); 

     Console.WriteLine("MyTask() started"); 
     for (var i = 0; i < 10; i++) 
     { 
      try 
      { 
       if (cancellationToken.IsCancellationRequested) 
        cancellationToken.ThrowIfCancellationRequested(); 

      } 
      catch (Exception ex) 
      { 
       return; 
      } 


      Console.WriteLine($"Counter in MyTask() = {i}"); 
      Thread.Sleep(500); 
     } 
     Console.WriteLine("MyTask() finished"); 
    } 
    static void Main(string[] args) 
    { 
     var cancelationTokenSource = new CancellationTokenSource(); 
     var task = Task.Factory.StartNew(MyTask, cancelationTokenSource.Token, 
      cancelationTokenSource.Token); 

     Thread.Sleep(3000); 

     try 
     { 
      cancelationTokenSource.Cancel(); 
      task.Wait(); 
     } 
     catch (Exception ex) 
     { 
      if(task.IsCanceled) 
       Console.WriteLine("Task has been cancelled"); 

      Console.WriteLine(ex.Message); 
     } 
     finally 
     { 
      cancelationTokenSource.Dispose(); 
      task.Dispose(); 
     } 

     Console.WriteLine("Main finished"); 
     Console.ReadLine(); 
    } 
} 

我想開始新的任務,並在一段時間後取消一個簡單的控制檯應用程序。是否有任何其他方式來實現這個結果而不是使用這個

if(cancellationToken.IsCancellationRequested) 
     cancellationToken.ThrowIfCancellationRequested(); 

for循環中的每次迭代?爲什麼我們必須在每次迭代時檢查cancellationToken.IsCancellationRequested,也許我們可以使用其他的東西?

+3

就是這麼做的。當你有一個很長的任務p時,就是這樣實現的,以便允許中斷。 –

+0

@DanielProtopopov如果任務被取消,我們必須單次檢查evey –

+0

即使在彙編程序中它是如何完成的 - 一個在循環之外控制的變量 - 你期望什麼? –

回答

1

在這種特定情況下,您可以避免使用.ThrowIfCancellationRequested(),而只需使用break來停止執行循環,然後完成Task。在更深的任務樹中,ThrowIfCancellationRequested更有用,其中有更多的後代,並且保持取消更加困難。

if (cancellationToken.IsCancellationRequested) 
{ 
    break; 
} 

Stephen Toub有一個good explanation關於OCE投擲是如何更多的承認。

如果任務的身體也監測取消標記,並拋出包含令牌(這是什麼ThrowIfCancellationRequested做)的OperationCanceledException,那麼當任務看到OCE,它會檢查OCE的令牌是否匹配該任務的令牌。如果是,則將該異常視爲確認協作取消,並且任務轉換爲取消狀態(而不是故障狀態)。

0

不知道你的反對在每個迭代上檢查是什麼,但如果你不想去檢查每一次迭代,不管出於什麼原因,檢查i值:

例如此檢查每10個循環:

if (i % 10 == 0 && cancellationToken.IsCancellationRequested) 

你必須檢查的原因是,這樣你就可以決定哪裏是最好停止工作,這樣的工作是不是不一致的狀態。雖然所有你通過不頻繁檢查來實現的任務是一個取消較慢的任務,也許這會導致一個不太敏感的用戶體驗。例如。任務將在500ms之前結束,現在可能需要10x,5秒。

但是,如果每個循環非常快,並且每個循環檢查標誌都會證明顯着增加了任務花費的總時間,然後檢查每個循環是否有效。