14

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

CancellationTokenSource _cts;

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

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

4

1 回答 1

18

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

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

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

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

这意味着,尽管您已经处置了 CTS,但它的对象仍被令牌引用。因此,它仍然不符合收集条件。

现在让我们看看CancellationToken.IsCancellationRequested

public bool IsCancellationRequested 
{
    get
    {
        return m_source != null && m_source.IsCancellationRequested;
    }
}

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

附带说明一下,如果您(出于某种原因)尝试通过它的 disposed 传递一个令牌CancellationTokenSource,您将点击一个ObjectDisposedException.

编辑:

我想补充两点。首先,让我说我不建议使用这种方法。它应该适用于某些代码执行路径,但不适用于所有路径。CancellationTokenSource通常只有在您使用它的WaitHandle财产时才应处置。否则,最好让 GC 进行清理。但是,因为这是一个口味问题,你可以选择任何你喜欢的。我当然建议您仅在确定任务已观察到取消请求后才进行处理。

根据 的用法WaitHandle,一旦您处置,它将被处置并归零,因此将无法访问。

于 2015-04-21T20:05:01.357 回答