Too many timers in .NET?

 
 
  • Gérald Barré

There are at least 6 different timer classes in .NET, each with its own purpose and use case. Here is a breakdown of the differences between them.

First, there are two UI-specific timers that execute code on the UI thread:

  • System.Windows.Forms.Timer
  • System.Windows.Threading.DispatcherTimer

Because callbacks run on the UI thread, you can interact with UI elements directly. Only one callback executes at a time, so thread safety is not a concern.

There is also a WebForms-specific timer: System.Web.UI.Timer. It generates a postback event on the server, but it belongs to legacy technology and is not covered in depth here.

Finally, there are 3 timers that are not UI-specific:

  • System.Threading.Timer
  • System.Threading.PeriodicTimer
  • System.Timers.Timer

System.Threading.Timer is the most basic timer. It schedules callbacks on the ThreadPool. If a handler takes longer to execute than the interval, it will be invoked again before the previous run completes, resulting in multiple handlers running in parallel.

C#
var timer = new System.Threading.Timer(
    callback: state => Console.WriteLine("tick"), // callback can be executed in parallel
                                                  // if the previous one is not completed
                                                  // before the next tick
    state: null, // Can be used to pass data to the callback (to avoid using a closure)
    dueTime: TimeSpan.Zero,           // Start the timer immediately
    period: TimeSpan.FromSeconds(1)); // Tick every second

// Pause the timer
timer.Change(dueTime: Timeout.Infinite, period: Timeout.Infinite);

System.Timers.Timer wraps System.Threading.Timer internally and exposes additional features such as AutoReset, Enabled, and SynchronizingObject, which let you configure how callbacks are executed. The Elapsed event supports multiple handlers, so a single timer can trigger several callbacks. Handlers can also be added or changed after the timer has started.

C#
var timer = new System.Timers.Timer(TimeSpan.FromSeconds(1));

// Support multiple handlers
timer.Elapsed += (sender, e) => Console.WriteLine("Handler 1");
timer.Elapsed += (sender, e) => Console.WriteLine("Handler 2");

// Support customizing the way the callback is executed (on the ThreadPool if not set)
timerComponent.SynchronizingObject = ...;

// Stop the timer after the first tick
timerComponent.AutoReset = false;

// Start the timer
timer.Start();

System.Threading.PeriodicTimer is the latest timer added to .NET. Its primary purpose is to support async handlers in a loop. Rather than a tick event, it exposes a WaitForNextTickAsync method that returns a ValueTask<bool> which completes when the next tick is ready. The bool value indicates whether the timer has been disposed, making it suitable for use in a while loop. This design prevents callbacks from overlapping.

C#
using var cts = new CancellationTokenSource();
using var periodicTimer = new PeriodicTimer(TimeSpan.FromSeconds(1));

// Simple usage, no concurrent callbacks, supports async _handlers_
while (await periodicTimer.WaitForNextTickAsync(cts.Token))
{
    Console.WriteLine("Tick");
    await AsyncOperation();
}

If you know of another timer in .NET, please let me know!

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?