CancellationTokenSource

CancellationTokenSource

大多数情况下,我将CancellationTokenSource用于超时目的。为了避免忘记dispose,当我完成CancellationTokenSource时,我使用的是using语句。但是在using语句结束之前,我总是在做CancellationTokenSource.Cancel()

如果未使用取消,是否有必要在处置前取消CancellationTokenSource吗?

这是我正在执行此操作的代码示例。

using (CancellationTokenSource TokenSource = new CancellationTokenSource(nTimeout * 1000))
{
  for (int i = 0; i < nLoop; i++)
  {
    if (TokenSource.Token.IsCancellationRequested)
    {
      bSuccess = false;
      break;
    }

    await Task.Delay(cDelay);
    // do some work
  }

  TokenSource.Cancel();
}

最佳答案

处置CancellationTokenSource后,基于此来源的令牌可能会抛出ObjectDisposedException,因此在处置该来源之后,请勿使用CancellationTokenSource.Token。幸运的是,我没有在您的代码中看到这种情况。

取消CancellationTokenSource时,它会更改状态并通知已为令牌注册的回调。但是,当您的代码将要处置CancellationTokenSource时,您已经使用令牌完成了操作,无需取消它。

因此,根据您的情况,无需在处置前取消CancellationTokenSource。但是,您的用例有些特殊。当您有后台任务时,您应该等待任务完成,然后再处理源(如我的第一段所述):

using (var cts = new CancellationTokenSource()) {
    var task = Task.Run(() => DoSomething(cts.Token));
    // Cancel cts or let it cancel itself based on a timeout.
    // Then wait for the task to end.
    await task;
}

09-05 09:26