2014-09-08 4 views
1

Идея : создать Task, который печатает все большее число звездочек. Когда пользователь нажимает Enter, Task печатает 10 звездочек, а затем останавливается.Задача продолжения не выполняется, когда задача отменена

код:

namespace CancellingLongRunningTasks 
{ 
    using System; 
    using System.Threading; 
    using System.Threading.Tasks; 

    class Program 
    { 
     static void Main() 
     { 
      var cancellationTokenSource = new CancellationTokenSource(); 
      var token = cancellationTokenSource.Token; 

      Task task = Task.Run(() => 
      { 
       int count = 1; 
       while (!token.IsCancellationRequested) 
       { 
        Console.WriteLine(new string('*', count)); 
        Thread.Sleep(1000); 
        count++; 
       } 
      }, token).ContinueWith(
       parent => 
       { 
        var count = 10; 
        while (count > 0) 
        { 
         Console.WriteLine(new string('*', count)); 
         Thread.Sleep(1000); 
         count--; 
        } 
       }, TaskContinuationOptions.OnlyOnCanceled); 

      Console.WriteLine("Press enter to stop the task."); 

      if (Console.ReadLine().Contains(Environment.NewLine)) 
      { 
       cancellationTokenSource.Cancel(); 
       task.Wait(); 
      } 
     } 
    } 
} 

вопрос: почему это не мое продолжение задача выполнена?

+0

возможный дубликат [CancellationTokenSource не ведет как ожидалось] (http://stackoverflow.com/questions/24346706/cancellationtokensource-not-behaving-as-expected) – i3arnon

ответ

5

Это не выполняется, потому что вы не активно отменяете Task, проверяя только, была ли запрошена отмена. Используйте CancellationToken.ThrowIfCancellationRequested, который бросает OperationCanceledException и превратит Task в отмененной состояние или просто выбросить исключение с соответствующим маркером:

Task task = Task.Run(() => 
{ 
     int count = 1; 
     while (!token.IsCancellationRequested) 
     { 
      Console.WriteLine(new string('*', count)); 
      Thread.Sleep(1000); 
      count++; 
     } 
     token.ThrowIfCancellationRequested(); 
}, token) 

Что эквивалентно:

Task task = Task.Run(() => 
{ 
     int count = 1; 
     while (!token.IsCancellationRequested) 
     { 
      Console.WriteLine(new string('*', count)); 
      Thread.Sleep(1000); 
      count++; 
     } 
     throw new OperationCanceledException(token); 
}, token)