System.Timers.Timer
memory management
application performance
resource disposal
.NET programming

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.

csharp
1using System;
2using System.Timers;
3
4public class StatusMonitor
5{
6    private readonly Timer _timer;
7
8    public StatusMonitor()
9    {
10        _timer = new Timer(5000);          // Fire every 5 seconds
11        _timer.Elapsed += OnTimerElapsed;
12        _timer.AutoReset = true;
13        _timer.Start();
14    }
15
16    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
17    {
18        Console.WriteLine($"Check at {e.SignalTime}");
19    }
20
21    // Without Dispose, this timer keeps firing even after
22    // StatusMonitor is no longer referenced
23}

Correct Disposal Pattern

Implement IDisposable on the owning class and dispose the timer in the Dispose method.

csharp
1using System;
2using System.Timers;
3
4public class StatusMonitor : IDisposable
5{
6    private readonly Timer _timer;
7    private bool _disposed;
8
9    public StatusMonitor()
10    {
11        _timer = new Timer(5000);
12        _timer.Elapsed += OnTimerElapsed;
13        _timer.AutoReset = true;
14        _timer.Start();
15    }
16
17    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
18    {
19        if (_disposed) return;
20        Console.WriteLine($"Check at {e.SignalTime}");
21    }
22
23    public void Dispose()
24    {
25        if (_disposed) return;
26        _disposed = true;
27
28        _timer.Stop();
29        _timer.Elapsed -= OnTimerElapsed;
30        _timer.Dispose();
31    }
32}
csharp
1// Usage with using statement
2using (var monitor = new StatusMonitor())
3{
4    Console.ReadLine(); // Timer fires while running
5}
6// Timer is stopped and disposed here

What Happens Without Disposal

When a timer is not disposed:

  1. Continued firing: The timer keeps invoking Elapsed even after the owning object is no longer used by application code.
  2. Memory leak: The delegate chain from Elapsed holds references to the handler's target object, preventing garbage collection.
  3. Race conditions: The handler may access disposed or nulled resources if other parts of the application have cleaned up.
csharp
1// Problematic: Timer outlives its owner
2public class Processor
3{
4    private Timer _timer;
5    private List<string> _buffer = new();
6
7    public Processor()
8    {
9        _timer = new Timer(1000);
10        _timer.Elapsed += (s, e) => _buffer.Add("tick");
11        _timer.Start();
12    }
13
14    // No Dispose — _timer keeps adding to _buffer indefinitely
15    // _buffer grows without bound
16}

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.

csharp
1// Stop: pauses, can restart
2_timer.Stop();
3_timer.Start(); // Works
4
5// Dispose: permanent cleanup
6_timer.Dispose();
7// _timer.Start(); // ObjectDisposedException

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.

csharp
1using System.Threading;
2
3public class HealthCheckService : IHostedService, IDisposable
4{
5    private Timer _timer;
6
7    public Task StartAsync(CancellationToken cancellationToken)
8    {
9        _timer = new Timer(DoCheck, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
10        return Task.CompletedTask;
11    }
12
13    private void DoCheck(object state)
14    {
15        Console.WriteLine("Health check");
16    }
17
18    public Task StopAsync(CancellationToken cancellationToken)
19    {
20        _timer?.Change(Timeout.Infinite, 0);
21        return Task.CompletedTask;
22    }
23
24    public void Dispose()
25    {
26        _timer?.Dispose();
27    }
28}

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() without Dispose() when the timer is no longer needed — stopped timers still hold resources and delegate references.
  • Not unsubscribing event handlers before disposal — the Elapsed handler can fire one last time between Stop() and Dispose() calls. Use a _disposed flag to guard the handler.
  • Creating timers in tight loops without disposal — each undisposed timer consumes thread pool resources.
  • Using System.Timers.Timer in ASP.NET without an IHostedService wrapper — the timer lifecycle is not tied to the application lifecycle, causing issues during shutdown.

Summary

  • Always dispose System.Timers.Timer when you are done with it.
  • Implement IDisposable on the owning class and call _timer.Dispose() in the Dispose method.
  • Unsubscribe Elapsed handlers and use a _disposed guard flag to prevent late-firing callbacks.
  • Use Stop() for temporary pauses, Dispose() for permanent cleanup.
  • In ASP.NET Core, prefer IHostedService with System.Threading.Timer for application-lifecycle-aware timers.

Course illustration
Course illustration