24

Here is a sample code that creates a new task that simulates a long running process. There is nothing much on the task as such and purely focuses on the cancelling features. I am using cancellation token to cancel the task and the code works fine for me.

CancellationTokenSource CTS = new CancellationTokenSource();

Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
          Thread.Sleep(5000);
       }
       else { Console.WriteLine("Thread Cancelled");break; }
   }
   return true;

}, CTS.Token, TaskCreationOptions.None);

PTask.Start();
Console.WriteLine("Hit Enter to cancel the Secondary thread you have started");
Console.ReadLine();
CTS.Cancel();
System.Console.WriteLine(PTask.Result);

But one thing that I could not understand is the token parameter (CTS.Token) that is being passed on to the Task constructor. What is the actual use of passing the parameter, when I can actually cancel the task even without passing token to the constructor.

Down below is a slightly modified version that works without the token parameter.

CancellationTokenSource CTS = new CancellationTokenSource();
Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
           Thread.Sleep(5000);
       }
       else
       {
           Console.WriteLine("Thread Cancelled");
           break;
       }
};
Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
Prabhu Murthy
  • 9,031
  • 5
  • 29
  • 36
  • 1
    I would recommend reading: http://blogs.msdn.com/b/pfxteam/archive/2009/05/22/9635790.aspx – Slugart Jun 01 '12 at 13:01
  • 2
    Does this answer your question? [Cancellation token in Task constructor: why?](https://stackoverflow.com/questions/3712939/cancellation-token-in-task-constructor-why) –  Feb 20 '20 at 12:37

1 Answers1

40

UPDATE: The following msdn question describes the reason:

Passing a token into StartNew associates the token with the Task. This has two primary benefits:

  1. If the token has cancellation requested prior to the Task starting to execute, the Task won't execute. Rather than transitioning to Running, it'll immediately transition to Canceled. This avoids the costs of running the task if it would just be canceled while running anyway.

  2. If the body of the task is also monitoring the cancellation token and throws an OperationCanceledException containing that token (which is what ThrowIfCancellationRequested does), then when the task sees that OCE, it checks whether the OCE's token matches the Task's token. If it does, that exception is viewed as an acknowledgement of cooperative cancellation and the Task transitions to the Canceled state (rather than the Faulted state).

Community
  • 1
  • 1
daryal
  • 14,643
  • 4
  • 38
  • 54
  • Are you saying the iscancelrequest check with the token of primary thread is unsafe. – Prabhu Murthy Jun 01 '12 at 12:58
  • I can not see any other reason of passing token to the constructor, but if you are asking whether i am 100% sure; well not. – daryal Jun 01 '12 at 13:04
  • I have updated, in fact this has nothing to do with thread safety. – daryal Jun 01 '12 at 13:09
  • 1
    Point 2 doesn't seem to be valid. `Task.Run(async () => { throw new OperationCanceledException(); }, new CancellationToken(false)).ContinueWith(tsk => Console.WriteLine(tsk.Status))` returns Canceled, not Faulted. – psaxton Oct 18 '16 at 16:34
  • @psaxton, I think you need to call ThrowIfCancellationRequested , not thowing the exception yourself. Calling ThrowIfCancellationRequested will pass additional data into the exception, see the source for ThrowIfCancellationRequested, also the same token must be passed to the lambda. – Tore Nestenius Jul 05 '23 at 14:00