在任务中调用CancellationTokenSource.Cancel()不会将Task.IsCanceled设置为true

时间:2015-01-13 18:03:48

标签: c# task-parallel-library resharper cancellationtokensource

如果我在与取消令牌关联的任务中调用cancellationTokenSource.Cancel,则OperationCancelledException被正确抛出,但task.IsCanceled并非始终更新并设置为true,正如预期的那样。

使用以下nUnit测试可以快速证明问题:

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();
}

当我运行此测试时,测试通过,但是,当我调试此测试(使用Resharper测试运行器)时,测试失败。

我认为这与Resharper没有任何关系,我认为Resharper可能会创建一些可能会在.Net中暴露问题的条件。或者,也许我只是在做一些完全错误的事情...... 任何见解?

1 个答案:

答案 0 :(得分:6)

等待Task时,请勿使用取消令牌。它导致Wait在任务状态设置之前抛出并继续执行断言。

这两件事情是并行发生的,所以它实际上是一个竞争条件,关于它是否发生,因此你试图复制问题时的问题以及调试时的正确行为。