7

So I know because of the Question Can Timers get automatically garbage collected? that the System.Timers.Timer will not be garbage collected in the first place.

But my actual question is - do i have to stop or dispose the Timer?

private void CreateTimer()
{
    var timer = new Timer();
    timer.Elapsed += TimerElapsed;
    timer.Interval = 30000;
    timer.AutoReset = true;
    timer.Enabled = true;
}

I mean this Timer will run forever. But now I have no need anymore for my object that created the Timer in the Method. Do I have to stop or dispose the Timer that it gets garbage collected?

Peter
  • 1,655
  • 22
  • 44
  • there is a difference between stop and dispose. Stopping a timer would be sth somebody would need during the lifecycle of the timer – apomene Sep 25 '17 at 12:37
  • You can check it yourself: Create something like MesseBox.Show on Elapsed, then kill it owner, e.g, by closing subWindow. – sTrenat Sep 25 '17 at 12:38
  • 1
    I don't think it will be garbage collected till you call `dispose` on it. It does not matter whether you `stop` the timer. More here: `Always call Dispose before you release your last reference to the Component. Otherwise, the resources it is using will not be freed until the garbage collector calls the Component object's Finalize method.` https://msdn.microsoft.com/en-us/library/3cc9y48w(v=vs.110).aspx – Faheem Sep 25 '17 at 12:41
  • 1
    @Achilles - There's no guarantee that there is a `Finalize` method or if there is if it is written correctly or if it is even called or not. The rule should be to always call `.Dispose()` explicitly. – Enigmativity Sep 25 '17 at 12:46
  • @Enigmativity I agree, one should always call `.Dispose()` explicitly, but in this case `Timer` inherits from `Component` which provides implementation for `Finalize()', so the documentation stands correct. Ref: https://msdn.microsoft.com/en-us/library/az5741fh(v=vs.110).aspx – Faheem Sep 25 '17 at 13:01
  • @Achilles - Yes, but there are still circumstances when the finalizer is not called. – Enigmativity Sep 25 '17 at 13:19
  • It is a common misconception that calling `Dispose()` on an object will ensure that the object gets garbage collected. In fact `Dispose()` will release any **unmanaged** resources held by the object, and in case of a timer I believe this amounts to releasing a non-managed Windows timer queue object. An object can only be garbage collected when it's no longer reachable by any roots. If the object still has unmanaged resources they should be released by the finalizer. However, this is bad because it happens after the unmanaged resource could be released and will add work to the finalizer thread. – Martin Liversage Sep 25 '17 at 14:07

1 Answers1

6

I don't think it will be garbage collected till you call .Dispose() on it. It does not matter whether you .Stop() the timer.

So it appears that calling Timer.Stop() or setting Timer.Enabled to false should be enough, because that would call Timer.Dispose() for you. Ref: Timer.Enabled

From MSDN:

Always call Dispose before you release your last reference to the Component. Otherwise, the resources it is using will not be freed until the garbage collector calls the Component object's Finalize method. More here

If you'd like it to be automatically disposed off, then put that logic in a separate method using the Timer.Elapsed property as explained Here.

Faheem
  • 1,423
  • 2
  • 13
  • 22
  • 1
    No - "I don't think it will be garbage collected till you call `.Dispose()` on it." - that's not correct. If there are no live references it will be GC'ed regardless of whether or not `.Dispose()` has been called. – Enigmativity Sep 25 '17 at 13:21
  • 2
    Stopping the timer is good enough, no explicit Dispose() is required. It is never required, not what IDisposable was meant to do. Winforms abuses it but that doesn't extend to the BCL classes. – Hans Passant Sep 25 '17 at 13:23
  • 1
    Looking at the implementation for Timer class, you are correct. `Timer.Stop()` actually sets `Enabled` to false, which calls `timer.Dispose()`, so calling `Timer.Stop()` should be enough. I'll update the answer. – Faheem Sep 25 '17 at 13:41
  • 2
    I agree that not calling `Dispose` is probably _good enough_ for non-critical apps, but I have to disagree with "it's never required". `Dispose` is akin to picking up trash after yourself, as opposed to relying on the city's cleaning crew to do it for you; it's what a good citizen does. Also, the fact that `Enabled` disposes of the timer is moot: there's no guarantee that this will keep happening in a future .NET version, or that there won't be other unmanaged resources added to the class that will need to be freed _in addition to_ the inner timer, which is what `Dispose` would take care of. – Paul Jun 27 '18 at 17:23