I tried to run a simple example on the cancellation of 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 that Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);
would print **"Task 2 cancelled? True"**
, but it printed "False".
Do you know what happened? Is that the expected behaviour? Thanks.
EDIT: to ensure that the task hasn't completed before the cancellation request is called. I added the Console.ReadLine()
.
A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource.
In this articleCreate and start a cancelable task. Pass a cancellation token to your user delegate and optionally to the task instance. Notice and respond to the cancellation request in your user delegate. Optionally notice on the calling thread that the task was canceled.
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.
First, maybe you misunderstand what IsCanceled
means? It doesn't mean “this Task
is pending cancellation, so it should complete shortly”, it means “this Task
has been canceled, it is now complete”.
If you didn't misunderstand that, think about what exactly the sequence of events is. What happens is this:
ThrowIfCancellationRequested()
is called, but the token wasn't canceled yet, so it doesn't throw.Thread.Sleep()
is called, so the thread running the Task
sleeps.Cancel()
is called.IsCanceled
is checked. The code in the Task
didn't have a chance to realize that the token was canceled, so it's still running, so IsCanceled
returns false
.ThrowIfCancellationRequested()
is called again, this time it throws, which actually cancels the Task
.This is why ISCanceled
is returning false
to you. If you want it to return true
, you could add something like Thread.Sleep(150)
before checking IsCanceled
, or, even better, actually wait for the Task
to complete.
The Task ended before you call for cancellation, take a look at the following below this may help to shed some more light on how to resolve your issue
By 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 is "really" started, but after it has been queued.
It's more a way to cancel a task that's scheduled to occur, but not started yet. Once the task is running, the only way to cancel it is cooperatively via your own checking within the method. Without this, you'd have to always start the task, then check it internally, which would add a lot of extra, unnecessary overhead
You can even read it from Cancellation token in Task constructor: why?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With