Once again: do not use the clock to measure time

In my post, Don’t depend on what you don’t control, I explained why you shouldn’t depend on the system clock for elapsed time measurements. That is, consider this code:

    var startTime = DateTime.Now;
    // perform some long-running operation
    var endTime = DateTime.Now;
    // compute elapsed time
    var elapsed = endTime - startTime;

That code will produce erroneous values if the system clock changes between time checks. Imagine your surprise when you discover that it took -56 minutes to run a 5-minute job, because you just happened to start the job at one minute before 2:00 AM on the day we set our clocks back for Daylight Saving Time.

The system clock can change at any time. You don’t control it.

There’s another way this can trip you up. Say you want your program to do something at 4:00 AM. You start the program some hours before that and set a timer to wake up when the prescribed amount of time has elapsed:

    TimeSpan delayTime = Settings.WakeupTime - DateTime.Now;
    System.Threading.Timer t = new System.Threading.Timer(
        TimerTickHandler, null, delayTime.TotalMilliseconds, -1);

That creates a one-shot timer that will execute TimerTickHandler when the specified amount of time has elapsed.

But it’s “spring ahead” weekend. You wanted the program to wake up at 4:00 AM, but the clock skipped ahead an hour so it’s 5:00 AM before the timer tick happens. Oops.

The cause is the same: assuming that the system clock increases one second for every second of time that elapses. It’s an incorrect assumption.

When the system clock changes due to an external event, any time interval based on the previous setting is invalid.

There are two ways around this problem. One is to create a timer that ticks every minute (or every second, depending on how accurate you want to be). The timer’s callback then checks the current system clock against the desired wakeup time and does whatever it’s supposed to do when they match. This works well, but I find it intellectually dissatisfying because it’s polling. Polling for time is such a waste of resources. (Never mind that a few instructions every second won’t be noticed.)

A better solution is to use a Waitable Timer. Unfortunately, the .NET Framework doesn’t have a Waitable Timer object. But one is available. See my article Waitable Timers in .NET with C#. Full source code is available at http://www.mischel.com/pubs/waitabletimer.zip.