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.TimerSystem.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.TimerSystem.Threading.PeriodicTimerSystem.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!