Canceling a running Task:

A long running Task can be cancelled in a multithreaded environment. The .NET Framework offers a special class that can help you cancel a running task.

CancellationToken

  1. CancellationTokenSource tokenSource= new CancellationTokenSource();  
  2. CancellationToken token = tokenSource.Token;  
  3. Task t1 = Task.Factory.StartNew(() =>  
  4.   {  
  5.    while (!token.IsCancellationRequested)  
  6.    {  
  7.       Console.Write("* ");  
  8.       Thread.Sleep(1000);  
  9.    }  
  10.   },
  11. token);  
  12. Console.WriteLine("Press any key to stop the task\n");  
  13. Console.ReadKey();  
  14. tokenSource.Cancel();  
  15. Console.WriteLine("\n\nPress any key to stop the task");  
  16. Console.ReadKey();  
A little explanation to the code above would make it clearer.

The CancellationToken is used in asynchronous task. The CancellationTokenSource token is used to signal that the Task should cancel itself.

In the above case, the operation will just end when cancellation is requested via Cancel() method. As the calling thread requests the cancellation on callee (i.e. Task running in another thread), outside users of the tasks won’t see anything different because the tasks will just have a RanToComplete state. The RanToComplete is the status of the task under consideration. If you want to signal to outside users that your task has been cancelled. You can do this by throwing an OperationCancelledException.
  1. CancellationTokenSource tokenSource = new CancellationTokenSource();  
  2. CancellationToken token = tokenSource.Token;  
  3. Task t1 = Task.Factory.StartNew(() =>  
  4.    {  
  5.      while (!token.IsCancellationRequested)  
  6.        {  
  7.           Console.Write("* ");  
  8.           Thread.Sleep(100); //Throw if cancelled  
  9.        }  
  10.      if (token.IsCancellationRequested)  
  11.        {  
  12.           token.ThrowIfCancellationRequested();  
  13.        }  
  14.       },
  15.      token);  
  16.      try  
  17.        {  
  18.           Console.WriteLine("Press any key to stop the task\n");  
  19.           Console.ReadKey();  
  20.           tokenSource.Cancel();  
  21.           t1.Wait();  
  22.        }  
  23.      catch (AggregateException ex)  
  24.        {  
  25.           Console.WriteLine(“Exception Occured {0}”, ex.InnerExceptions[0].Message);  
  26.        }  
  27.       Console.WriteLine("\n\nPress any key to stop the task");  
  28.       Console.ReadKey();  
  29.    }  
Instead of canceling your running task and catching exception to show user what has really happened, you can continue with another task only if the previous task has been cancelled. Make use of Continue With method which takes the returned value from the cancelled task as a parameter. The same is shown in the following code snippet.
  1. CancellationTokenSource tokenSource = new CancellationTokenSource();  
  2. CancellationToken token = tokenSource.Token;  

  3.    Task t1 = Task.Factory.StartNew(() =>  
  4.    {  
  5.      while (!token.IsCancellationRequested)  
  6.      {  
  7.       Console.Write("* ");  
  8.       Thread.Sleep(1000); //Throw if cancelled     
  9.       }  
  10.     }, 
  11.    token).ContinueWith((t) =>  
  12.    {  
  13.       t.Exception.Handle((e)=> true);  
  14.       Console.WriteLine("The Task is interrupted");  
  15.    },

  16. TaskContinuationOptions.OnlyOnCanceled);  
  17. Console.WriteLine("Press key any key to cancel\n");  
  18. Console.ReadKey();  
  19. tokenSource.Cancel();  
  20. Console.WriteLine("\n\nEnd Application");  
  21. Console.ReadKey();

Next Recommended Readings