Timers in C#

We often want to execute code at some point in the future, or repeatedly at some interval. C#’s built-in Timer class and System.Timers.Timer class make both of these tasks easy. We’ll look first at timers and then at periodic timers.

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // Timers represent a single event in the future. You
        // tell the timer how long you want to wait, and it
        // provides a Task that will complete at that time.
        // This timer will wait 2 seconds.
        var timer1 = new Timer(_ => Console.WriteLine("Timer 1 fired"), null, 2000, Timeout.Infinite);

        // We use Task.Delay to wait for the timer to complete
        await Task.Delay(2000);
        Console.WriteLine("Timer 1 fired");

        // If you just wanted to wait, you could have used
        // Thread.Sleep. One reason a timer may be useful is
        // that you can cancel it before it fires.
        // Here's an example of that.
        var cts = new CancellationTokenSource();
        var timer2 = new Timer(_ => Console.WriteLine("Timer 2 fired"), null, 1000, Timeout.Infinite);

        // Start a task that will cancel the timer after 500ms
        _ = Task.Run(async () =>
        {
            await Task.Delay(500);
            timer2.Change(Timeout.Infinite, Timeout.Infinite);
            Console.WriteLine("Timer 2 stopped");
        });

        // Give the timer2 enough time to fire, if it ever
        // was going to, to show it is in fact stopped.
        await Task.Delay(2000);
    }
}

The first timer will fire ~2s after we start the program, but the second should be stopped before it has a chance to fire.

$ dotnet run
Timer 1 fired
Timer 2 stopped

In this C# version:

  1. We use the System.Threading.Timer class, which is similar to Go’s timer.
  2. Instead of channels, we use the timer’s callback to execute code when the timer fires.
  3. We use Task.Delay instead of time.Sleep for non-blocking waits.
  4. To stop a timer, we use the Change method with Timeout.Infinite as the parameters.
  5. We use async/await for asynchronous operations, which is more idiomatic in C# than creating separate threads.

This example demonstrates basic timer usage in C#, including creating, waiting for, and stopping timers.