Too many timers in .NET?

 
 
  • GĂ©rald BarrĂ©
 

There are at least 6 different timers classes in .NET! Each timer has its purpose and use-case. I will try to explain the differences between them.

First, there are UI-specific timers. These timers are used to execute code on the UI thread. They are:

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

These timers execute the callback on the UI thread. So, it means you can interact with the UI in both cases. Also, as the event is raised on the UI thread, there is only one callback executed at a time. So, you don't have to worry about thread-safety.

Second, there is one timer for WebForms: System.Web.UI.Timer. This timer generates a postback event on the server. But let's not talk about legacy tech… Sorry if you would like to learn more about this timer…

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

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

System.Threading.Timer is the most basic timer. It schedules the callback on the ThreadPool. If the handler takes more time to execute than the interval, the handler will be executed again and you end up with 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 uses System.Threading.Timer internally, and expose a few more features such as AutoReset, Enabled, or SynchronizingObject which allow configuring how the callback is executed. Also, the Tick event allows registering multiple handlers. So, one timer can trigger multiple handlers. You can also change the handler after the timer has been 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 the .NET libraries. The main goal of this timer is to be used in a loop and to support async handlers. It doesn't have a Tick event, but it exposes a WaitForNextTickAsync method. This method returns a ValueTask<bool> which is completed when the next tick is ready. The bool value indicates if the timer has been disposed. So, you can use it in a while loop. Thanks to this design, callbacks cannot overlap.

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 about another timer in .NET, please let me know!

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

Follow me: