Mikeyg36
Mikeyg36

Reputation: 2828

Calling CancellationTokenSource.Cancel() within a task does not set Task.IsCanceled to true

If I call cancellationTokenSource.Cancel within the task associated with the cancellation token, the OperationCancelledException is correctly thrown, however, task.IsCanceled is NOT always updated and set to true, as would be expected.

The problem can be quickly demonstrated with the following nUnit test:

var cancellationTokenSource = new CancellationTokenSource();
Task task = Task.Factory.StartNew(() =>
{                                
    cancellationTokenSource.Cancel();
    cancellationTokenSource.Token.ThrowIfCancellationRequested();                
}, 
cancellationTokenSource.Token);

try
{
    task.Wait(cancellationTokenSource.Token);                
}
catch (OperationCanceledException)
{
}

if (task.IsCanceled)
{
    Assert.Pass();
}
else
{
    Assert.Fail();
}

When I run this test, the test passes, however, when I DEBUG this test (using the Resharper test runner), the test fails.

I don't think this has anything to do with Resharper, I think Resharper just may be creating some conditions that perhaps expose an issue in .Net. Or, maybe I am just doing something completely wrong... Any insights?

Upvotes: 2

Views: 1074

Answers (1)

Servy
Servy

Reputation: 203804

Don't use the cancellation token when waiting on the Task. It's causing Wait to throw and move on to the assert before the task's status gets set.

The two things are happening in parallel, so it's actually a race condition as to whether or not it happens, hence the issues you've had trying to replicate the issues and the correct behavior when debugging.

Upvotes: 6

Related Questions