当我的计时器滴答作响时..NET 内存泄漏

本文关键字:NET 内存 泄漏 我的 计时器 滴答 | 更新日期: 2023-09-27 17:56:58

我有一个.NET System.Threading.Timer 计时器,它每60秒滴答一次,并在每次滴答时引入内存泄漏。

在计时器的每个刻度时,代码都会分配一个 IDisposable 对象(称为 SocketsMessageConnector)...但我确实正确处理了它。

我运行了 .NET 内存探查器,每隔 60 秒我就会看到我的 SocketsMessageConnector 类的新实例在内存中徘徊(所以 15 分钟后,我有 15 个实例)。内存探查器验证实例是否确实已释放,但它显示由 TimerCallback 根的实例,该实例由 _TimerCallback 根,该 根植于 GCHandle...

这是怎么回事?为什么 TimerCallback 会保留在每个计时器滴答时创建的新实例?

附言。探查器在拍摄快照之前强制使用 2 个 GC,所以我知道它实际上是泄漏,而不仅仅是 GC 的优化。

当我的计时器滴答作响时..NET 内存泄漏

仅仅因为它已被处理,并不意味着它已被垃圾回收。

尝试将计时器更改为每秒运行两次,然后让它运行 10 分钟。现在检查有多少类对象仍然"在内存中徘徊"。如果确实存在内存泄漏,则将有 1200 个对象。但是,如果垃圾回收已经加入,你的数量就会少得多——可能不到 100。