C#
timer
stop timer
programming
.NET

C - how do you stop a timer?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C#, stopping a timer depends on which timer type you are using, because .NET has several timer classes with different threading behavior. The general rule is to stop future ticks first and then dispose the timer when you are permanently finished with it.

System.Timers.Timer

For System.Timers.Timer, stopping is usually done with Stop() or by setting Enabled to false.

csharp
1using System;
2using System.Timers;
3
4class Program
5{
6    static void Main()
7    {
8        var timer = new Timer(1000);
9        timer.Elapsed += OnElapsed;
10        timer.Start();
11
12        Console.ReadLine();
13        timer.Stop();
14        timer.Dispose();
15    }
16
17    static void OnElapsed(object? sender, ElapsedEventArgs e)
18    {
19        Console.WriteLine("tick");
20    }
21}

Stop() prevents future callbacks from being scheduled, but it does not magically rewind a callback that has already started running.

System.Threading.Timer

System.Threading.Timer uses a different API. To stop it, change the due time and period to Timeout.Infinite.

csharp
1using System;
2using System.Threading;
3
4class Program
5{
6    static void Main()
7    {
8        using var timer = new Timer(
9            _ => Console.WriteLine("tick"),
10            null,
11            dueTime: 0,
12            period: 1000);
13
14        Console.ReadLine();
15        timer.Change(Timeout.Infinite, Timeout.Infinite);
16    }
17}

If the timer will never be used again, dispose it as well. The stopping action and the cleanup action are related, but they are not the same thing.

UI Timers

UI frameworks have timer classes that are tied to the UI thread. Windows Forms Timer and WPF DispatcherTimer are common examples, and both are normally stopped with Stop().

csharp
1DispatcherTimer timer = new DispatcherTimer();
2timer.Interval = TimeSpan.FromSeconds(1);
3timer.Tick += (_, _) => Console.WriteLine("ui tick");
4timer.Start();
5
6// later
7timer.Stop();

These timers are useful for UI updates because their callbacks already execute in the thread context that owns the interface.

Stop Versus Dispose

A good mental model is:

  • stop disables future ticks
  • dispose releases resources and ends the timer's usable lifetime

If the timer might be restarted later, stopping is enough. If the owning object is shutting down, disposing is usually the right final step.

This distinction matters in services, desktop apps, and background components where repeated timer creation can otherwise leak resources or keep callbacks alive longer than intended.

Callback Safety Still Matters

Stopping a timer does not automatically cancel work that is already executing. If the callback touches shared state or performs I/O, shutdown code must still coordinate safely with that callback.

A simple guard flag can help:

csharp
1private volatile bool _stopping;
2
3private void OnElapsed(object? sender, ElapsedEventArgs e)
4{
5    if (_stopping) return;
6    Console.WriteLine("work");
7}

Set _stopping = true before stopping and disposing if the callback should become a no-op during shutdown.

It is also worth checking whether the timer is periodic or one-shot. Some shutdown bugs come from assuming the timer will fire repeatedly when it was configured for a single callback, or vice versa.

In test code and short-lived components, timer ownership is another common source of confusion. The safest design is to make one object clearly responsible for starting, stopping, and disposing the timer so lifecycle bugs do not get split across multiple classes.

Common Pitfalls

Mixing up timer classes is a frequent mistake because the APIs are similar but not identical.

Stopping a timer but never disposing it when the owner is done can leave subscriptions and resources around longer than intended.

Assuming Stop() cancels a callback that is already in progress leads to race conditions during shutdown.

Summary

  • The exact stop operation depends on which .NET timer class you are using.
  • 'System.Timers.Timer and most UI timers stop with Stop().'
  • 'System.Threading.Timer stops future ticks with Change(Timeout.Infinite, Timeout.Infinite).'
  • Dispose timers when they are no longer needed permanently.

Course illustration
Course illustration

All Rights Reserved.