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.Timer
is doing behind the scenes. It is a wrapper around the System.Threading.Timer
class. When the timer starts it creates a new System.Threading.Timer
instance and passes it a callback method in the System.Timers.Timer
instance. 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.Timer
instance is not collected and does not stop automatically. Removing the Elapsed
event handler will not solve this problem because that delegate only holds a reference to the TrayForm
instance. Again, it is the System.Threading.Timer
that is keeping a reference to the System.Timers.Timer
. The whole reference chain remains rooted because the system has to reference the System.Threading.Timer
for it to work.
Here is the reference chain:
System => _TimerCallback => Callback => System.Threading.Timer => Callback => System.Timers.Timer
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.AddTimerNative
method which is marked MethodImplOptions.InternalCall
so we cannot see exactly how the reference is rooted below this point. But, it is rooted nonetheless.
If you disable the timer via Enabled = false
or Stop
then it will dispose the underlying System.Threading.Timer
which should in turn stop referencing the System.Timers.Timer
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With