当我的计时器计时时... .NET内存泄漏 [英] When my timer ticks.... .NET Memory Leak

查看:79
本文介绍了当我的计时器计时时... .NET内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个.NET System.Threading.Timer计时器,它每60秒滴答一次,并且每次滴答都会引起内存泄漏.

在计时器的每个滴答声中,代码都会分配一个IDisposable对象(称为SocketsMessageConnector)...但是我确实将其正确处理.

我运行了.NET Memory Profiler,每60秒我就会看到一个SocketsMessageConnector类的新实例在内存中徘徊(因此15分钟后,我就有15个实例).内存探查器会验证该实例是否确实已被处置,但是它显示了一个实例,该实例以TimerCallback为根,该实例以_TimerCallback为根,该_TimerCallback以GCHandle为根...

这是怎么回事?为什么TimerCallback坚持在每个计时器滴答声中创建的新实例?

PS.探查器会在拍摄快照之前强制使用2个GC,因此我知道这实际上是泄漏,而不仅仅是GC的优化.

解决方案

仅仅是因为已被处置,并不意味着它已经被垃圾收集了.

尝试将计时器更改为每秒运行两次,然后让其运行10分钟.现在,检查您的类对象中有多少仍在内存中徘徊".如果确实有内存泄漏,则将有1200个对象.但是,如果垃圾回收"已经投入使用,那么您的垃圾收集就会大大减少-也许不到100.

I have a .NET System.Threading.Timer timer that ticks every 60 seconds and introduces a memory leak on each tick.

On each tick of the timer, the code allocates an IDisposable object (called SocketsMessageConnector)...but I do dispose it correctly.

I ran .NET Memory Profiler and every 60 seconds I see a new instance of my SocketsMessageConnector class lingering in memory (so after 15 minutes, I have 15 instances). The memory profiler verifies that the instance is in fact disposed, but it shows the instance rooted by a TimerCallback, which is rooted by a _TimerCallback, which is rooted by a GCHandle...

What's up here? Why is the TimerCallback holding on to the new instance created on every timer tick?

PS. The profiler forces 2 GCs before taking a snapshot, so I know it IS in fact a leak and not just an optimization by the GC.

解决方案

Just because it's been disposed, doesn't mean that it's been Garbage Collected yet.

Try changing your timer to run twice a second, and then let it run for 10 minutes. Now check how many of your class objects are still "lingering in memory". If you truely have a memory leak, you'll have 1200 objects. But if Garbage Collection has jumped in, you'll have considerably less - perhaps under 100.

这篇关于当我的计时器计时时... .NET内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆