4

Obviously, System.Threading.Timer callback should be expected to be late a bit. However, can it be called early?

For instance, if you start a Stopwatch and schedule the timer to run the callback in 1000 ms, is it possible that the Stopwatch will be showing 999 in the callback? Or can we count on the fact that it must show 1000 or more?

public sealed class EarlyTiming : IDisposable
{
    public EarlyTiming()
    {
        stopwatch = new Stopwatch();
        stopwatch.Start();

        timer = new Timer(TimerCallback, null, 1000, Timeout.Infinite);
    }

    public void Dispose()
    {
        timer.Dispose();
    }

    private readonly Timer timer;
    private readonly Stopwatch stopwatch;

    private void TimerCallback(object state)
    {
        var elapsedMs = stopwatch.ElapsedMilliseconds;

        if (elapsedMs < 1000)
            Console.WriteLine("It was early! (" + elapsedMs + " ms)");

        try
        {
            stopwatch.Restart();
            timer.Change(1000, Timeout.Infinite);
        }
        catch (ObjectDisposedException) { }
    }
}
relatively_random
  • 4,505
  • 1
  • 26
  • 48
  • You're probably just losing a millisecond when setting up the timer. Start the stopwatch after you init the timer and it all looks fine. – DavidG Mar 30 '17 at 09:19
  • Possibly of interest [How accurate is System.Diagnostics.Stopwatch?](http://stackoverflow.com/q/394020/) – H H Mar 30 '17 at 09:22
  • 1
    I don't think it's explicitly documented. All they [do say](https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx) is that you're limited to the resolution of the system clock but they don't even say what rounding occurs. – Damien_The_Unbeliever Mar 30 '17 at 09:26
  • @DavidG It's not that there is an issue with the code provided. The question is should I expect the timer to be early sometimes when writing code or will the "It was early!" never ever be printed out. – relatively_random Mar 30 '17 at 09:39
  • @Damien_The_Unbeliever So is that a yes? It could conceptually be early if it rounds the time down? – relatively_random Mar 30 '17 at 09:41
  • 2
    I think its a "it is conceivable for an implementation of the .NET Framework to exhibit such behaviour but whether any current implementation does exhibit such behaviour is unknown". – Damien_The_Unbeliever Mar 30 '17 at 09:43
  • @relatively_random My point is that you **will** get "It was early!!" being printed out with this code, especially on a slower machine. – DavidG Mar 30 '17 at 09:53
  • @DavidG Ah, of course. Fixing, thanks. – relatively_random Mar 30 '17 at 09:54
  • @DavidG On second thought, no. If you start the stopwatch early, then it can only make it seem like *more* time has passed. If you start the stopwatch after starting the timer, you could make it seem like the timer was early even though it's just the OS putting your thread on hold for a while so you didn't start the timer on time. – relatively_random Mar 30 '17 at 09:58
  • Yes, it's all about the accuracy of the timer and the rounding that occurs on your machine. Unfortunately computers don't work in nice decimal blocks :) – DavidG Mar 30 '17 at 10:03

0 Answers0