Timer, event and garbage collection : am I missing something?

Consider the following code :

class TestTimerGC : Form
{
    public TestTimerGC()
    {
        Button btnGC = new Button();
        btnGC.Text = "GC";
        btnGC.Click += (sender, e) => GC.Collect();
        this.Controls.Add(btnGC);

        System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
        tmr.Interval = 1000;
        tmr.Tick += (sender, e) => this.Text = DateTime.Now.ToString();
        tmr.Start();
    }
}

If I'm not mistaken, after the tmr variable goes out of scope, the Timer isn't referenced anywhere, so it should be eligible for garbage collection. But when I click the GC button, the timer continues to run, so I guess it wasn't collected...

Does anyone have an explanation for that ?

PS: it's not a real program of course, I was just trying to prove a point to someone... but my proof didn't work ;)


Solution 1:

OK, I think I know what's going on... I looked at the code of the Timer class with Reflector, and I found the following instruction in the setter of the Enabled property :

this.timerRoot = GCHandle.Alloc(this);

So, when it is started, the timer allocates a GCHandle for itself, which prevents its collection by the GC...