CancellationTokenSource 与 CancellationTokenSourceToken

1. CancellationTokenSourceCancellationToken 是什么关系

可以理解成这样:

  • CancellationTokenSource(CTS) → “遥控器”
    它是发信号的人,我们可以调用 .Cancel() 来通知任务:“你该停了”。

  • CancellationToken(Token) → “遥控器的接收器”
    它只是一个只读的信号,任务内部只能用它来接收是否被取消,不能去取消别人。

CancellationTokenSource   ----产生---->   CancellationToken

2. 什么时候传 CancellationTokenSource

一般不建议跨方法传 CancellationTokenSource,因为:

  • CTS 有 .Cancel().Dispose() 方法,生命周期很容易被别人乱操作。
  • 如果多个方法共享同一个 CTS,很容易出现遇到的 Dispose 冲突

典型的例外场景
调用方需要在方法内部主动触发取消,才会传 CTS,比如:

public void StartSomething(CancellationTokenSource cts) {
    // 方法内部某个条件触发
    if (需要取消) {
        cts.Cancel();
    }
}

这种情况比较少见,大多数时候我们只是想发取消信号的人自己管理 CTS,不让别人动它。


3. 什么时候传 CancellationToken

99% 的异步任务传的应该是 CancellationToken 而不是 CTS,因为:

  • Token 不能被 .Cancel().Dispose(),所以任务只能用它接收取消信号,而不会乱动。
  • 调用方控制 CTS,保证线程安全,方法内部不需要担心 Dispose 冲突。

例如:

public async Task DoWorkAsync(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        // 执行某些任务
        await Task.Delay(100, token); // 如果取消,这里会抛 TaskCanceledException
    }
}

调用方:

var cts = new CancellationTokenSource();
await DoWorkAsync(cts.Token); // 只传 Token

4. 总结口诀

  • 要控制任务生命周期 → 自己持有 CancellationTokenSource(发信号的人)
  • 只需要监听取消信号 → 只传 CancellationToken(收信号的人)
  • 不要跨方法传 CTS,除非方法里确实需要主动 .Cancel() 它(很少)
posted @ 2025-08-12 17:22  青云Zeo  阅读(39)  评论(0)    收藏  举报