Can an object containing an active Timer (System.Timers.Timer
) be garbage collected, if no other object is referencing it?

- 2,692
- 2
- 28
- 55
2 Answers
There are two basic ways that a Timer stays referenced even if you don't store a reference somewhere:
As long as the timer is enabled. There's an underlying System.Threading.Timer that actually generates the event. The CLR keeps a list of active timers, the callback delegate object of them keeps the Timer referenced.
By the Elapsed event handler if it is not static. That extends the lifetime of the Timer instance to at least the lifetime of the class object that contains the Elapsed event handler.
There is no failure mode here. The only possible way to get a reference back to the timer is through the Elapsed event handler's sender argument. If you disable the timer then there is no longer a way to get a reference so it is appropriate for the object to be collected.
A fairly classic way to get in trouble with this Timer and lose Elapsed events is when you have the AutoReset property set to false. A very nasty issue is that any exceptions raised in the Elapsed event handler are swallowed without any diagnostic. Which will bypass the call you'd have to restart the timer at the end. Do favor System.Threading.Timer, it doesn't have this problem.

- 922,412
- 146
- 1,693
- 2,536
-
+1. Do you know why an unreferenced `System.Threading.Timer` can be GC'ed but not `System.Timers.Timer`? – Stephen Cleary Feb 10 '11 at 18:44
-
@Stephen, not sure what you mean. Same rules, list of active timers inside the CLR, the callback references the target object. And an unrefed System.Timers.Timer *can* be collected if it isn't enabled. – Hans Passant Feb 10 '11 at 18:47
-
My unreferenced, periodic `System.Threading.Timer` is GCed, but my unreferenced, auto-reset `System.Timers.Timer` is not. Event handler does not reference timer. Can you confirm? (.NET 4.0 Client) – Stephen Cleary Feb 10 '11 at 19:29
-
@Stephen - this is a very different question. Why don't you start your own? Please do provide evidence how you know that it doesn't get collected. – Hans Passant Feb 10 '11 at 19:33
-
http://stackoverflow.com/questions/4962172/why-does-a-system-timers-timer-survive-gc-but-not-system-threading-timer – Stephen Cleary Feb 10 '11 at 20:19
-
_"By the Elapsed event handler if it is not static"_ -- please clarify this statement. Because it seems like you are saying that the handler somehow retains a reference to the timer, making it reachable and preventing GC. That's backwards from what actually happens: the object _publishing_ the event retains a reference to the handler, which can keep that object alive. But it doesn't keep the timer alive, except for whatever brief period of time the handler is actually executing (since the timer reference is passed as a parameter). ... – Peter Duniho Oct 12 '19 at 01:05
-
... Ironically, you suggest `System.Threading.Timer`, which is the timer implementation that has the "you have to explicitly retain a reference to the timer" rule, to prevent it from being GC'ed. It just trades one easy-to-fall-into pitfall for another. :( – Peter Duniho Oct 12 '19 at 01:06
Yes. Timer
will be GC'd if left unreferenced, even while running.
The documentation says:
The code contains declarations of the timer variable at the class level and inside Main. To see how aggressive garbage collection can affect a timer that is declared inside a long-running method, you can comment out the class-level declaration and uncomment the local variable. To keep the timer from being collected, uncomment the GC.KeepAlive method at the end of Main.

- 868,454
- 176
- 1,908
- 1,964
-
2
-
1Then the docs need fixing: http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx is about 4.5 – H H Aug 06 '13 at 06:55
-
Current documentation appears to have removed this erroneous statement. – Peter Duniho Oct 12 '19 at 01:07