Someone emailed me that I hadn’t showed any sample code of how to use the thread pool timer. Whoops, what a good point! There are basically two ways to use it, so I’ll show you two bits of code. But the first thing you need to do is install the NuGet package. So open your package manager console and type

Install-Package UltimateTimer

OK! Now the following code should compile:


using UltimateTimer;
class Program
{
    static ThreadPoolTimer timer;

    static void Main(string[] args)
    {
        timer = ThreadPoolTimer.Create(() => OnTimer(timer));
        timer.SetTimer(DateTime.Now.AddSeconds(3),
            msPeriod: 0,
            acceptableMsDelay: 0);
        Console.WriteLine("Press any key to stop timer");
        Console.ReadLine();
        timer.Dispose();
    }

    private static void OnTimer(ThreadPoolTimer timer)
    {
        Console.WriteLine("Timer was called back! Resetting timer. The time is now " + DateTime.Now.ToString());
        timer.SetTimer(DateTime.Now.AddSeconds(3), 0, 0);
    }
}

In this example

-we have a single timer,
-we use an anonymous lambda to make whatever parameters we want get passed to our callback (including the timer itself), and
-the timer will NEVER be called back in two threads at the same time because there is only ever one timer event queued at a time. If Console.WriteLine were not a thread-safe API (actually it is thread-safe) then this would be the easiest way of writing a safe program.

In our second example, we will set the timer to have msPeriod > 0 so that it recurs automatically without us resetting the schedule, and remove the timer.SetTimer() call in the timer callback.

using UltimateTimer;
class Program
{
    static ThreadPoolTimer timer;

    static void Main(string[] args)
    {
        timer = ThreadPoolTimer.Create(() => OnTimer(timer));
        timer.SetTimer(DateTime.Now.AddSeconds(3),
            msPeriod: 3000,
            acceptableMsDelay: 0);
        Console.WriteLine("Press any key to stop timer");
        Console.ReadLine();
        timer.Dispose();
    }

    private static void OnTimer(ThreadPoolTimer timer)
    {
        Console.WriteLine("Timer was called back! Resetting timer. The time is now " + DateTime.Now.ToString());
    }
}

In this case if our timer delegate were not thread-safe, we would have a possible race condition. The reason is that the timer keeps adding new timer events  to its dispatcher queue even if OnTimer() has not finished running yet. However, luckily in this case all we are doing is Console.WriteLine, so we’re pretty safe. If instead we were modifying a shared object that has potential race condition issues, we would need to use a lock() statement in OnTimer, like this:

 

private static void OnTimer(ThreadPoolTimer timer)
{
    lock (mylock)
    {
        // touch shared state
    }
}

I hope that helps explain how to use the timer! And just remember to Dispose() your timers once you don’t want any further callbacks.

And one last thing – because ThreadPoolTimer inherited directly from SafeHandle it has a whole bunch of crazy methods on it that you NEVER want to call. The only methods you want to call are ThreadPoolTimer.Create, timer.SetTimer(), and timer.Dispose(). Happy coding.