.NET异步方法运行时,未使用的局部变量会被垃圾回收吗?
.NET异步方法中局部变量的垃圾回收问题
核心结论
异步方法中的局部变量,只要不再被后续代码(包括异步恢复执行的代码)引用,就会被垃圾回收器(GC)标记为可回收,哪怕对应的Task长时间运行也不例外。
针对示例代码的分析
以你提供的异步方法为例(修正语法错误后):
async void IterateForAnIternity() { int c = 0; SomeClass _class = new SomeClass(); while(true) { int newVar = c * c; LogMessage log = new LogMessage($"new var is now {newVar}"); log.Print(); var _tmp = _class.ReturnSomeBigStruct(); await Task.Yield(); } }
newVar:在log.Print()执行后,直到本次循环结束都不再被引用,GC可以在await之前回收它(值类型会直接释放栈空间,若为引用类型则标记回收)log:调用Print()后,后续代码不再使用这个实例,因此它会被标记为可回收,不会因为异步方法持续运行而一直占用内存_tmp:作为结构体(值类型),在await前就会被清理;如果是引用类型,只要后续无引用,同样会被GC回收c和_class:由于循环全程持续使用,它们会一直存活在状态机中,直到方法终止(此方法为无限循环,因此会一直存在)
异步状态机的内存管理细节
.NET异步方法会被编译为状态机类,局部变量会被转换为状态机的字段。但JIT编译器和GC会识别哪些字段在后续状态中不再被访问,一旦变量不再被任何根引用(包括状态机中不再使用的字段),就会被纳入回收范围,不会造成内存泄漏。
官方文档参考
.NET官方文档的「垃圾回收」和「异步编程」章节明确了这一原则:GC的回收逻辑不区分同步或异步方法,核心判断标准是对象是否还存在有效的引用链。
内容的提问来源于stack exchange,提问作者Cool guy
相关产品推荐
相关产品推荐

