Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Thread sleep method is most precise: Monitor.Wait vs System.Timer vs DispatchTimer vs Threading.Timer

What .NET object (or technique) is the most precise at launching a thread every XXX milliseconds? What are the tradeoffs?

For example:

        int maxDurationMs = 1000;
        while (true)
        {
            DateTime dt = DateTime.UtcNow;
            DoQuickStuff()
            TimeSpan duration1 =  DateTime.UtcNow - dt;
            int sleepTime = maxDurationMs - duration1.Milliseconds;
            if (sleepTime > 0)
                System.Threading.Thread.Sleep(sleepTime);
        }

or

       // CPU Intensive, but fairly accurate
       int maxDurationMs = 1000;
        while (true)
        {
            DateTime dt = DateTime.UtcNow;
            DoQuickStuff()
            while (true)
            {
                if (dt.AddMilliseconds(maxDurationMs) >= DateTime.UtcNow)
                    break;
            }
        }

Alternate methods of doing the same thing, but with varying degrees of accuracy and tradeoffs (CPU, etc)

  • System.Timer
  • DispatchTimer
  • System.Threading.Timer
  • Thread.Join
  • .NET 4.0 Task
  • Thread.Sleep()
  • Monitor.Wait(obj, timespan)
  • Multimedia Timers (thanks Brian Gideon)
  • Win32 High Resolution timers
  • Something else?
like image 558
makerofthings7 Avatar asked Mar 27 '26 19:03

makerofthings7


2 Answers

I have never actually used them myself, but Multimedia Timers are said to have the best resolution of any timer service in Windows. The .NET BCL does not have a wrapper for this timer service yet so you will have to do the P/Invoke calls yourself.

Another option might be to use Stopwatch together with some standard Thread.Sleep calls in a tight loop. I am not sure how much luck you would have with this approach, but it might be more accurate than a plain old Thread.Sleep call by itself. I have never tried it, but anything is worth a shot I suppose.

I did some experiments and I discovered that changing the thread priority to ThreadPriority.Highest made a considerable difference. It reduced the standard deviation of the interval by quite a bit on each technique I tried.

like image 130
Brian Gideon Avatar answered Mar 30 '26 10:03

Brian Gideon


Don't use DateTime: its accuracy is limited to around 16ms on most systems. (See Eric Lippert's blog)

The most accurate method would be to have a dedicated thread running a while loop with a System.Diagnostics.Stopwatch object to count the time.

Even with the most precise and accurate timer in existance, raising an event exactly every x milliseconds is no simple task given the unpredictability of CPU time slices: I suggest looking into how games do their main loop (achieving a stable 30fps with lag compensation, for instance). A good example is OpenTK's GameWindow, specifically the RaiseUpdateFrame method.

like image 43
Asik Avatar answered Mar 30 '26 11:03

Asik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!