异步代码示例为何引发内存泄漏:任务完成却无法被垃圾回收
问题原因与解决方案
核心原因
- Visual Studio的Make Object ID(你标记的
$1)功能会对目标对象持有强引用,这个引用来自调试器上下文,和代码逻辑无关。只要这个标记没被清除,GC就无法回收该对象,这就是第一个t1任务始终存在的根本原因。 - 你手动给第一个
t1分配了对象ID,这个引用会一直保留在调试会话中,哪怕后续创建了新的任务,第一个被标记的对象也不会被回收。
解决办法
- 清除调试器的对象ID标记:在Visual Studio即时窗口执行
Debug.ClearObjectIDs()命令,或者右键点击监视窗口里的$1选择「Delete Object ID」,之后再执行GC操作,就能看到对象被正常回收。 - 正确排查内存泄漏:如果要验证真实场景的泄漏,别用调试器对象ID判断。改用内存快照对比:操作前后各拍一次快照,查看对象实例的增长情况;或者用性能探查器的内存分析功能,追踪对象的根引用链(比如静态集合未清理、事件订阅未取消、异步闭包意外持有引用等)。
- 你的示例代码本身无泄漏:在没有调试器标记的情况下,执行完
DoAsyncStuff并完成GC后,t1任务和MyClass实例都会被正常回收。
内容的提问来源于stack exchange,提问作者Steven Lemmens
相关产品推荐
相关产品推荐

