CancellationToken实例化、IsCancellationRequested修改及取消机制问题
CancellationToken 使用相关问题解答
首先给出核心结论:
- 直接实例化的
CancellationToken是不可变结构,创建完成后就无法修改IsCancellationRequested属性,只有通过关联的CancellationTokenSource调用Cancel方法,才能修改对应Token的取消状态。 - 要实现可主动触发的任务取消逻辑,不能使用
new CancellationToken(),必须使用CancellationTokenSource.Token。
详细说明
1. 直接创建的CancellationToken的特性
CancellationToken本身是值类型,你直接用new创建时只有两种初始化可能:
- 无参数构造
new CancellationToken():得到的Token的IsCancellationRequested永远为false,不可能进入取消状态,和直接使用CancellationToken.None完全等价。 - 带布尔参数构造
new CancellationToken(true):得到的Token的IsCancellationRequested永远为true,创建后就固定为已取消状态,无法再修改。
这两种场景下创建的Token都没有关联任何CancellationTokenSource,不存在后续修改状态的可能。
2. 可触发取消的场景必须用CancellationTokenSource.Token
CancellationTokenSource才是真正控制取消状态的对象,它暴露的Token属性返回的令牌是和当前Source绑定的状态视图:当你调用CancellationTokenSource.Cancel()时,所有和它关联的CancellationToken的IsCancellationRequested都会同步变为true,进而触发所有监听这个Token的取消逻辑。
只要你的业务场景需要后续主动触发取消,就必须创建CancellationTokenSource实例,把它的Token传递给异步任务/方法,之后在需要取消的时候调用Source的Cancel方法即可。
3. 直接new CancellationToken()的适用场景
只有两种场景你可以直接实例化CancellationToken,不需要用到CancellationTokenSource:
- 你调用的方法要求传入
CancellationToken参数,但当前业务场景完全不需要支持取消,直接传new CancellationToken()或者更简洁的CancellationToken.None即可。 - 你需要一个固定为已取消状态的令牌,比如参数校验失败后要快速返回一个已取消的Task,直接用
new CancellationToken(true)会比创建CancellationTokenSource再调用Cancel要更简洁高效,示例:
if (参数非法) { return Task.FromCanceled(new CancellationToken(true)); }
内容的提问来源于stack exchange,提问作者user17493770
相关产品推荐
相关产品推荐

