If there is one thing that .NET has plenty of it is timers.

The timer is an object that exposes functionality allow you to write code to fire either:

  1. After a certain duration
  2. When your logic detects a certain time or date.

There are 5 at present:

System.Timers.Timer

This timer is designed for use in server applications and multi-threaded environments.

System.Threading.Timer

This timer makes use of threads from the runtime thread pool.

System.Windows.Forms.Timer

This is a timer optimized for the Windows Forms UI framework, and must in fact be used in the context of a Window.

System.Web.UI.Timer

This timer is for use in web applications, on the full .NET framework.

System.Windows.Threading.DispatcherTimer

This is a timer optimized for the Windows Presentation Foundation, and is integrated into the dispatcher queue.

To add onto this, .NET 6 has introduced a sixth timer - the PeriodicTimer.

Why a sixth timer?

This one is designed to be used in an asynchronous context.

Unlike the other timers that are wired to events, a PeriodicTimer is used like this:

// Create a timer that fires every 5 seconds
using (var timer = new PeriodicTimer(TimeSpan.FromSeconds(5)))
{
    // Wire it to fire an event after the specified period
    while (await timer.WaitForNextTickAsync())
    {
        Console.WriteLine($"Firing at {DateTime.Now}");
    }
}

This should print the following to the console:

The PeriodicTimer also supports cancellation using the Cancellation framework introduced in .NET 4.

For example we can setup our timer to stop after 20 seconds.

// Create a cancellaton token source that will cancel in 20 seconds
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20));
// Create a timer that fires every 5 seconds
using (var timer = new PeriodicTimer(TimeSpan.FromSeconds(5)))
{
    // Wire it to fire an event after the specified period
    while (await timer.WaitForNextTickAsync(cts.Token))
    {
        Console.WriteLine($"Firing Cancellable timer at {DateTime.Now}");
    }
}

If you run this you should see the following:

Note that an OperationCancelled exception is thrown, that you can catch and then manage as appropriate.

You can also cancel the task yourself by obtaining a CancellationToken from the CancellationTokenSource and then canceling yourself.

// Create a cancellation token source
var cts = new CancellationTokenSource();
// Create a timer that fires every 5 seconds
using (var timer = new PeriodicTimer(TimeSpan.FromSeconds(5)))
{
    // Create a counter to simulate logic
    var counter = 0;
    // Wire it to fire an event after the specified period
    while (await timer.WaitForNextTickAsync(cts.Token))
    {
        // Cancel when the counter gets to 5
        if (counter == 5)
            cts.Cancel();
        Console.WriteLine($"Running logic at {DateTime.Now}");
        counter++;
    }

If you run this you should get the following:

Not that this time instead of an OperationCancelledExceptoion you get a TaskCancelledException.

Naturally you will write an error handler to catch and handle this exception, rather than what has been done in this example.

Thoughts

This seems like a very clean, lightweight timer for async timed operations.

The code is in my Github

TLDR

The PeriodicTimer is a timer designed for async usage.

This is Day 17 of the 30 Days Of .NET 6 where every day I will attempt to explain one new / improved thing in the upcoming release of .NET 6.

Happy hacking!