30 Days Of .NET 6 - Day 17 - New Timer - PeriodicTimer
[.NET, C#, 30 Days Of .NET 6]
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:
- After a certain duration
- 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!