GC.Collect调用后未释放内存,服务运行多日内存持续上涨问题求助
VB.NET 服务内存泄漏问题修复指南
核心问题定位
- 类级别全局对象持有引用导致无法回收:你在EDIService类中声明的
SqlConnection、DataSet、DataTable、ManualResetEvent、自定义类Onling.clsSQLExecutes实例均为类级成员,每次循环如果给这些变量赋值新实例,旧实例会因为一直被类持有引用,无法被GC正常回收。 IDisposable接口实现失效:你声明了类实现IDisposable,但没有给出对应的Dispose逻辑,也没有在循环或服务停止时主动释放类持有的非托管资源,注释掉的Dispose调用完全没有发挥作用。- 未正确释放单次循环的资源:核心逻辑
CheckForFiles方法未贴出代码,大概率存在以下问题:文件流、数据库操作对象未释放,静态集合持续追加元素未清理,事件订阅后未取消,非托管API调用后未释放对应资源。 - 手动调用GC的冗余逻辑无效:你在循环中手动调用
GC.Collect、GC.WaitForPendingFinalizers的操作完全没有意义,只要对象还被持有引用,手动触发GC也无法回收对应内存,反而会额外增加性能开销。
可落地修复方案
- 将临时对象改为局部变量:所有单次循环用到的
DataSet、DataTable、SqlConnection、文件流等对象,全部放到CheckForFiles方法内部声明为局部变量,不要放到类级别作为全局成员,避免一直持有引用。 - 用Using语句包裹所有IDisposable对象:所有实现了IDisposable的类型,包括数据库连接、命令、读取器、文件流、内存流等,都用VB的
Using语句包裹,作用域结束后会自动释放资源,不需要手动关闭或释放。 - 补全IDisposable实现逻辑:在EDIService的Dispose方法中,手动释放类必须保留的全局IDisposable对象,包括
MsSQLConn、stoppedEvent、Comm等,同时将所有DataTable、DataSet对象设置为Nothing,解除引用。 - 排查CheckForFiles逻辑:检查该方法中是否存在静态集合只增不删的逻辑,是否有事件订阅后没有取消,是否调用了非托管接口没有释放对应内存,是否有大对象(大于85000字节)一直被持有引用。
- 移除所有手动GC调用代码:删除所有手动调用
GC.Collect、GC.WaitForPendingFinalizers的代码,GC有自动回收策略,手动调用无法解决泄漏问题,反而会影响服务性能。
内容的提问来源于stack exchange,提问作者robinhood1995
相关产品推荐
相关产品推荐

