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.