Is it necessary to dispose System.Timers.Timer if you use one in your application?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Yes, you should dispose System.Timers.Timer when you are done with it. Timer implements IDisposable because it holds internal OS resources and event subscriptions that the garbage collector cannot clean up promptly. Failing to dispose timers can cause event handlers to fire after their owning objects are logically gone, leading to memory leaks and unexpected behavior.
Why Disposal Matters
System.Timers.Timer internally uses System.Threading.Timer, which registers a callback with the thread pool. Until disposed, the timer keeps firing its Elapsed event at the configured interval, and the delegate reference prevents the garbage collector from collecting objects referenced by the handler.
Correct Disposal Pattern
Implement IDisposable on the owning class and dispose the timer in the Dispose method.
What Happens Without Disposal
When a timer is not disposed:
- Continued firing: The timer keeps invoking
Elapsedeven after the owning object is no longer used by application code. - Memory leak: The delegate chain from
Elapsedholds references to the handler's target object, preventing garbage collection. - Race conditions: The handler may access disposed or nulled resources if other parts of the application have cleaned up.
Stop vs Dispose
Stop() (or setting Enabled = false) pauses the timer but does not release resources. The timer can be restarted. Dispose() permanently releases all resources and the timer cannot be reused.
Call Stop() when you want to pause temporarily. Call Dispose() when you are done with the timer permanently.
Timer in ASP.NET and Background Services
In ASP.NET Core, prefer IHostedService with System.Threading.Timer or PeriodicTimer (.NET 6+) instead of System.Timers.Timer. The hosted service lifecycle handles start and stop automatically.
Common Pitfalls
- Relying on the garbage collector to clean up timers — the GC is non-deterministic and timer callbacks may fire many times before collection occurs.
- Calling only
Stop()withoutDispose()when the timer is no longer needed — stopped timers still hold resources and delegate references. - Not unsubscribing event handlers before disposal — the
Elapsedhandler can fire one last time betweenStop()andDispose()calls. Use a_disposedflag to guard the handler. - Creating timers in tight loops without disposal — each undisposed timer consumes thread pool resources.
- Using
System.Timers.Timerin ASP.NET without anIHostedServicewrapper — the timer lifecycle is not tied to the application lifecycle, causing issues during shutdown.
Summary
- Always dispose
System.Timers.Timerwhen you are done with it. - Implement
IDisposableon the owning class and call_timer.Dispose()in theDisposemethod. - Unsubscribe
Elapsedhandlers and use a_disposedguard flag to prevent late-firing callbacks. - Use
Stop()for temporary pauses,Dispose()for permanent cleanup. - In ASP.NET Core, prefer
IHostedServicewithSystem.Threading.Timerfor application-lifecycle-aware timers.

