It matters when you register your cancellation action. You are doing some work you want to be able to cancel. So it makes no sense to register the cancellation action after you already finished your work, correct? CancellationToken merely gives you the signal that cancellation was requested, you need to act on it. This logic needs to be in place before you start your work otherwise you will miss the cancellation signal. Consider following code:
void Main()
{
var source = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => DoWork(source.Token));
Thread.Sleep(1000);
source.Cancel();
task.Wait();
}
void DoWork(CancellationToken token)
{
object locker = new Object();
token.Register(() =>
{
lock (locker)
{
Console.WriteLine("Cancel signal");
Monitor.Pulse(locker);
}
});
lock (locker)
{
var cancelled = Monitor.Wait(locker, 2000);
Console.WriteLine("Cancelled: " + cancelled);
}
}
The above example runs about 1sec and prints following output:
Cancel signal
Cancelled: True
If you move the registration after the actual work like this:
void DoWork(CancellationToken token)
{
object locker = new Object();
lock (locker)
{
var cancelled = Monitor.Wait(locker, 2000);
Console.WriteLine("Cancelled: " + cancelled);
}
token.Register(() =>
{
lock (locker)
{
Console.WriteLine("Cancel signal");
Monitor.Pulse(locker);
}
});
}
Then it will run 2sec and print this:
Cancelled: False
Cancel signal
Please note that the cancellation action is invoked even it was registered after the token was signaled. This is consistent with
MSDN[
^] saying:
If this token is already in the canceled state, the delegate will be run immediately.