Possible Duplicate:
Timer, event and garbage collection : am I missing something?
private void TrayForm_Load(object sender, EventArgs e)
{
System.Timers.Timer HideMeTimer = new System.Timers.Timer(2500);
HideMeTimer.Elapsed +=
delegate(object sender2, System.Timers.ElapsedEventArgs e2)
{
this.Invoke(new Action(somestuff));
};
HideMeTimer.Start();
GC.Collect();
}
Can somebody please show me how the compilator will translate this?
Or good explanation why the timer keep on ticking after the load event.
(Is not the rule when the last reference is gone, to an variable, the GC will sometime
kill the object !)
You need to understand what
System.Timers.Timeris doing behind the scenes. It is a wrapper around theSystem.Threading.Timerclass. When the timer starts it creates a newSystem.Threading.Timerinstance and passes it a callback method in theSystem.Timers.Timerinstance. The system references this callback delegate as long as the timer remains enabled.We also know that delegates keep a reference to an instance of the class containing the target method. This is why your
System.Timers.Timerinstance is not collected and does not stop automatically. Removing theElapsedevent handler will not solve this problem because that delegate only holds a reference to theTrayForminstance. Again, it is theSystem.Threading.Timerthat is keeping a reference to theSystem.Timers.Timer. The whole reference chain remains rooted because the system has to reference theSystem.Threading.Timerfor it to work.Here is the reference chain:
When you track this through with Reflector or ILSpy you can see that the “System” in the reference chain above comes into play via the
TimerBase.AddTimerNativemethod which is markedMethodImplOptions.InternalCallso we cannot see exactly how the reference is rooted below this point. But, it is rooted nonetheless.If you disable the timer via
Enabled = falseorStopthen it will dispose the underlyingSystem.Threading.Timerwhich should in turn stop referencing theSystem.Timers.Timer.