2016-10-31 22 views
0

如何通過在任務內部而不是在任務調用的方法內部轉發令牌來取消長時間運行的任務?C#取消令牌作爲任務第二個參數

我的代碼:

class Program 
{ 
    static void Main(string[] args) 
    { 
     CancellationTokenSource token = new CancellationTokenSource(); 
     Stopwatch stop = new Stopwatch(); 
     stop.Start(); 

     Task.Factory.StartNew(() => myLongTask(6000), token.Token); 

     while (true) 
     { 
      Thread.SpinWait(1000); 
      if (stop.ElapsedMilliseconds > 3000) 
      { 
       token.Cancel(); 
      } 
     } 
    } 

    public static void myLongTask(int time) 
    { 
     var sw = Stopwatch.StartNew(); 
     Console.WriteLine("Task started"); 
     while (true) 
     { } 
     Console.WriteLine("Task ended"); 
    } 
} 

這個任務永遠不會被取消。如果我在myLongTask()方法中轉發令牌,我可以連續收聽取消是否被觸發,但是,我不確定...您如何以這種方式做到這一點?

+3

取消是*合作*。通過這種性質,代碼必須被寫爲*應該尊重的取消標記的*知道*。 –

+0

有沒有辦法做到這一點呢? – Norgul

+0

另一種方法是先佔權,如例如。 'Thread.Abort' - 但它很容易導致難以清理的狀態 - 這就是爲什麼現代取消方法採用合作風格的原因。所以,不,我不會推薦一種替代方案 - 使需要取消的代碼知道取消令牌。 –

回答

1

您需要檢查自己的令牌的狀態,例如:

public static void myLongTask(int time, CancellationToken token) 
{ 
    var sw = Stopwatch.StartNew(); 
    Console.WriteLine("Task started"); 
    while (true) 
    { 
     token.ThrowIfCancellationRequested(); 
    } 
    Console.WriteLine("Task ended"); 
} 

這樣做的原因,因爲在評論中提到的,即取消是一個合作行動。如果不是,那麼框架就不得不迫使你的任務停止,這可能會讓你的應用程序處於不合需要的狀態。通過檢查自己,您可以完全控制取消操作的意義。

+0

我知道...我想找到一種方法來執行該功能的範圍以外 – Norgul

+0

@Norgul您希望您的功能在取消時的行爲如何? CancellationToken的想法是提供一個定義的取消(這意味着Workload功能需要知道令牌並處理它)。 – Console

+0

我希望它打破連續循環,並停止執行,除了例外 – Norgul