You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何释放CancellationTokenSource会同步释放其关联的Linked CTS资源?

为什么释放作业专属CancellationTokenSource会连带回收关联的Linked CancellationTokenSource?

问题背景

在.NET 4.7.2控制台应用排查内存泄漏时,通过三组测试发现:

  • 仅释放关联的linkedCts:仅能回收一半对象
  • 同时释放linkedCts与作业专属Cts:所有非全局CancellationTokenSource都被回收
  • 仅释放作业专属Cts:效果与同时释放两者一致,所有非全局对象都被回收

即使linkedCts关联着存活的全局CancellationToken,该现象依然存在。


核心原因:LinkedCts的内部依赖与生命周期关联

要理解这个现象,得从CancellationTokenSource.CreateLinkedTokenSource的内部实现逻辑说起:

  1. LinkedCts的依赖关系
    当你创建linkedCts时,它会内部注册回调,监听所有传入的CancellationToken(包括全局ct和作业Cts的token)的取消事件。这里的关键是:

    • linkedCts会持有对作业Cts的token的强引用,以便监听其状态变化
    • 作业Cts不会持有linkedCts的引用
  2. 释放作业Cts时的连锁反应
    当你释放作业Cts时,它会完成内部的取消信号,标记自身为已完成状态。此时:

    • linkedCts监听的作业Cts token触发取消事件,linkedCts会自动进入取消状态
    • linkedCts内部会清理对作业Cts token的引用,同时自身的资源(如等待句柄、回调注册)会被释放
    • 虽然linkedCts还关联着全局ct,但全局ct的CancellationTokenSource并不会持有linkedCts的引用——linkedCts只是注册了全局ct的回调,而这种注册不会形成反向的强引用链。只要你的代码中没有其他地方持有linkedCts的引用,GC就可以回收它。
  3. 仅释放linkedCts时的局限性
    释放linkedCts只会清理它自身的资源,但作业Cts并没有被触发释放或取消,它仍然处于存活状态(只要代码中还有对它的引用,或者未完成其生命周期)。因此作业Cts无法被GC回收,也就出现了“仅能回收一半对象”的结果。


关键结论

linkedCts的生命周期本质上依赖于所有关联的token的状态:当其中一个关联的token(这里是作业Cts的token)被释放/取消,linkedCts会自动完成自身的生命周期,不再被其他引用链锁定,最终被GC回收。而反过来,仅释放linkedCts不会影响作业Cts的生命周期,因此无法回收作业Cts对象。

内容的提问来源于stack exchange,提问作者Maddin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:31:11