是否在任务取消时正确处理CancellationTokenSource的代码?

时间:2015-04-21 18:02:01

标签: c# .net cancellationtokensource

我在我面前看到这个代码,我很怀疑:

CancellationTokenSource _cts;

public void Dispose();
{
    _cts.Cancel();
    _cts.Dispose();
    _task.Wait(); //wait for the task to be canceled!?
}

取消后直接调用_cts.Dispose()是否安全?如果想要这样做,是否会取消取消任务所需的CancellationTokenSource底层资源以成功等待CancellationToken?

1 个答案:

答案 0 :(得分:14)

  

取消后直接调用_cts.Dispose()是否安全?

为了解这一点,我们需要了解取消CancellationTokenSource时会发生什么。

当您取消CancellationTokenSource时,它会继续调用通过CancellationToken注册的任何回调,CancellationToken.Register()通过CancellationToken.IsCancellationRequested方法保存对其父源的引用。

现在,当您处置CTS时,尝试从令牌中取消注册已注册的任何链接回调。如果它当前正在执行,它将等到它的委托完成。

这意味着,虽然你已经处理了你的CTS,但它的对象仍然被令牌引用。因此,它仍然没有资格收集。

现在让我们看一下public bool IsCancellationRequested { get { return m_source != null && m_source.IsCancellationRequested; } }

ObjectDisposedException

这意味着在处理时,检查取消将产生真实。这意味着,在调用dispose之后等待完成任务是安全的。

作为旁注,如果您(由于某种原因)尝试通过处置CancellationTokenSource传递令牌,您将点击CancellationTokenSource

修改

我想添加两件事。首先,我要说我不建议使用这种方法。它应该适用于某些代码执行路径,但不适用于所有代码。 WaitHandle通常只有在您使用WaitHandle财产时才会被处置。否则,可以将它留给GC进行清洁。但是,由于这是一个风味问题,你可以选择你喜欢的。我肯定会建议您在确定任务已经遵守取消请求后才进行处置。

根据{{1}}的使用情况,一旦您处置,它就会被处理掉,因此不会可以访问。