Multithreaded Timers

System.Threading.Timer is the simplest multithreaded timer: it has just a constructor and two methods. In the following example, a timer calls the Tick method, which writes “tick…” after five seconds have elapsed, and then every second after that, until the user presses Enter:

Example

using System;
using System.Threading;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            // First interval = 5000ms; subsequent intervals = 1000ms
            Timer tmr = new Timer(Tick, "tick...", 5000, 1000);
            Console.ReadLine();
            tmr.Dispose(); // This both stops the timer and cleans up.
        }
        static void Tick(object data)
        {
            // This runs on a pooled thread
            Console.WriteLine(data); // Writes "tick..."
        }
    }
}

You can change a timer’s interval later by calling its Change method. If you want a timer to fire just once, specify Timeout.Infinite in the constructor’s last argument. The .NET Framework provides another timer class of the same name in the System.Timers namespace. This simply wraps the System.Threading.Timer, providing additional convenience while using the identical underlying engine. Here’s a summary of its added features:

  • A Component implementation, allowing it to be sited in Visual Studio’s designer.
  • An Interval property instead of a Change method
  • An Elapsed event instead of a callback delegate
  • An Enabled property to start and stop the timer (its default value being false)
  • Start and Stop methods in case you’re confused by Enabled
  • An AutoReset flag for indicating a recurring event (default value is true)
  • A SynchronizingObject property with Invoke and BeginInvoke methods for

safely calling methods on WPF elements and Windows Forms controls.

Example

using System;
using System.Timers;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Timer tmr = new Timer(); // Doesn't require any args
            tmr.Interval = 500;
            tmr.Elapsed += tmr_Elapsed; // Uses an event instead of a delegate
            tmr.Start(); // Start the timer
            Console.ReadLine();
            tmr.Stop(); // Stop the timer
            Console.ReadLine();
            tmr.Start(); // Restart the timer
            Console.ReadLine();
            tmr.Dispose(); // Permanently stop the timer
        }
        static void tmr_Elapsed(object sender, EventArgs e)
        {
            Console.WriteLine("Tick");
        }
    }
}

Multithreaded timers use the thread pool to allow a few threads to serve many timers. This means that the callback method or Tick event may fire on a different thread each time it is called. Furthermore, a Tick always fires (approximately) on time— regardless of whether the previous Tick has finished executing. Hence, callbacks or event handlers must be thread-safe.