Cancel job

I tried to run a simple example with canceling a task like the one below

CancellationTokenSource tokenSource2 = new CancellationTokenSource(); CancellationToken token2 = tokenSource2.Token; Task task2 = new Task(() => { for (int i = 0; i < int.MaxValue; i++) { token2.ThrowIfCancellationRequested(); Thread.Sleep(100); Console.WriteLine("Task 2 - Int value {0}", i); } }, token2); task2.Start(); Console.WriteLine("Press any key to cancel the task"); Console.ReadLine(); tokenSource2.Cancel(); Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled); 

I expected Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled); prints **"Task 2 cancelled? True"** , but prints "False" .

Do you know what happened? Is this expected behavior? Thanks.

EDIT: so that the task is not completed before the cancellation request is called. I added Console.ReadLine() .

+6
source share
3 answers

First, maybe you don’t understand what IsCanceled means? This does not mean that "this Task waiting for cancellation, so it should be completed soon", it means that "this Task been canceled, it is now completed."

If you do not understand this correctly, think about exactly what sequence of events. What's happening:

  • ThrowIfCancellationRequested() is called, but the token has not yet been canceled, so it does not drop. Called
  • Thread.Sleep() , so the thread starting Task is asleep.
  • Cancel() .
  • IsCanceled . The code in Task not able to understand that the token was canceled, so it still works, so IsCanceled returns false .
  • ThrowIfCancellationRequested() is called again, this time it throws, which actually cancels Task .

This is why IsCanceled returns false you. If you want it to return true , you could add something like Thread.Sleep(150) before checking IsCanceled or, better yet, actually expect Task to complete.

+5
source

The task is over before you apply for cancellation, take a look at the following below, this can help shed light on how to solve your problem.

Reading from here http://social.msdn.microsoft.com/Forums/da-DK/parallelextensions/thread/9f88132a-f8bd-4885-ab63-645d7b6c2127 , it seems that the token is used to cancel the task before the task "really" launched, but after it has been queued.

This is more of a way to cancel a task that should happen, but has not yet begun. Once the task is running, the only way to cancel it is to jointly test your method inside the method. Without this, you will always have to run the task and then check it internally, which will add a lot of extra unnecessary service messages

You can even read it from the cancellation token in the task designer: why?

+2
source

This is not an answer, but too long to write in a comment

 CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; Task task = new Task(() => { for (int i = 0; i < int.MaxValue; i++) { cancellationToken.ThrowIfCancellationRequested(); Console.WriteLine("Task 2 - Int value {0}", i); } }, cancellationToken); task.Start(); cancellationTokenSource.Cancel(); try { task.Wait(); } catch (AggregateException ae) { if(ae.InnerExceptions.Single() is TaskCanceledException) Console.WriteLine("Caught TaskCanceledException"); else Console.WriteLine("Did not catch canceled"); } Console.WriteLine("Task 2 cancelled? {0}", task.IsCanceled); 
  • The above code prints the expected, and I never got the fingerprint "Task 2 - Int {0}", so I don’t think it was finished before being canceled.
  • Note that canceling a task throws an exception in my example
  • There are some patterns for handling exceptions using tasks that may be useful for reading.
+2
source

All Articles