How Accurate Is Thread.Sleep(Timespan)

How accurate is Thread.Sleep(TimeSpan)?

Your thread is sharing CPU Time with other threads. The Sleep will end as soon as it is your turn again and the kernel notices the sleep time has elapsed, so it is not that accurate.

CPU load, process priorities, number of concurrent threads, even from other processes, will have effect upon it.

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

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.

Why is Thread.Sleep so harmful

The problems with calling Thread.Sleep are explained quite succinctly here:

Thread.Sleep has its use: simulating lengthy operations while testing/debugging on an MTA thread. In .NET there's no other reason to use it.

Thread.Sleep(n) means block the current thread for at least the number
of timeslices (or thread quantums) that can occur within n
milliseconds.
The length of a timeslice is different on different versions/types of
Windows and different processors and generally ranges from 15 to 30
milliseconds. This means the thread is almost guaranteed to block for
more than n milliseconds. The likelihood that your thread will
re-awaken exactly after n milliseconds is about as impossible as
impossible can be. So, Thread.Sleep is pointless for timing.

Threads are a limited resource, they take approximately 200,000 cycles
to create and about 100,000 cycles to destroy. By default they
reserve 1 megabyte of virtual memory for its stack and use 2,000-8,000
cycles for each context switch. This makes any waiting thread a
huge waste.

The preferred solution: WaitHandles

The most-made-mistake is using Thread.Sleep with a while-construct (demo and answer, nice blog-entry)

EDIT:

I would like to enhance my answer:

We have 2 different use-cases:

  1. We are waiting because we know a
    specific timespan when we should continue (use Thread.Sleep, System.Threading.Timer or alikes)

  2. We are waiting because some condition changes some time ...
    keyword(s) is/are some time! if the condition-check is in our code-domain, we
    should use WaitHandles - otherwise the external component should
    provide some kind of hooks ... if it doesn't its design is bad!

My answer mainly covers use-case 2

Why is Thread.Sleep is not precise for long durations?

Thread.Sleep is not designed for long accurate sleeps like you are doing. You should be using somthing like System.Threading.Timer. You can give it a first run time of midnight, and have it go off every 24 hours. the Timer(TimerCallback, Object, TimeSpan, TimeSpan) constructor is exactly what you are looking for.

.net thread.sleep inaccurate

As mentioned, accurate timings generally need a thread/process that is not going to time sliced out, to do this, you must Spin rather than Sleep.

Option 1

If you want absolute accuracy over anything else, I would use a dedicated high priority thread with a Stopwatch.

bool running = true;
Thread t = new Thread(() =>
{
Stopwatch sw = Stopwatch.StartNew();
while (running)
{
if (sw.ElapsedMilliseconds >= 20)
{
RunCode();
sw.Restart();
}
}
}) { Priority = ThreadPriority.Highest, IsBackground = true };

t.Start();

// ...

running = false;
t.Join();

Option 2

Bit more slimmed down, doesn't run on a different thread but still spins.

while (true) 
{
SpinWait.SpinUntil(() => false, TimeSpan.FromMilliseconds(20));
RunCode();
}

Option 3

Some open source high resolution timer code. e.g. https://gist.github.com/HakanL/4669495

Using Delay(TimeSpan) or Thread.Sleep doesn’t properly work in VMware

I can unfortunately not help you with fixing the VMWare end, aside from two off ideas:

  • If there is anything that passes through Threads directly to the Host CPU, you could try turning them off. It would be bad for performance, but might avoid issues with the Thread (Manager) and starting OS running on slightly different clocks.

  • I do I have a different approach you could try. One that relies a whole lot less on Thread/Async and similar Delay systems. Something that might be slightly more robust, against whatever is causing this. This difference was purely by accident - it started it's live as a example for a very basic Rate Limiting System, to be run in a seperate thread:

    integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);

while(true){
if(DateTime.Now >= dueTime){
//insert code here

//Update next dueTime
dueTime = DateTime.Now.AddMillisconds(interval);
}
else{
//Just yield to not tax out the CPU
Thread.Sleep(1);
}
}

This one only uses the Thread mechanics for the "low CPU load when idle" part. Everything else is based on the hopefully more stable DateTime System.

Do note that short Intervalls are poorly supported, even 20 ms might already be beyond the limit. DateTime.Now() is not remotely as accurate as as the type can be precise, so it only remotely works for dual or tripple digit Intervalls. Delay and Sleep do actually support Millisecond precision.

Does Threading.Thread.Sleep accepts ticks?

That falls in the "it depends" category. You could, say, be using it in a Silverlight app that runs on a Mac. But a standard Windows desktop app uses the operating system's Sleep() call which accepts a sleep time expressed only in milliseconds.

That's not where it ends, by default Windows can only sleep a thread with an accuracy that depends on the operating system clock interrupt. Which is, by default, 1/64 of a second, 0.015625 seconds on most machines. So if you Thread.Sleep(1) then you'll actually sleep for about 16 milliseconds. Or more.

You can jack up the interrupt rate by pinvoking timeBeginPeriod(1). Sleeps are now accurate to a millisecond, plus or minus a bunch due to scheduling inaccuracies. Something you should never do on a battery-powered machine. And don't forget to pinvoke timeEndPeriod().

Why does Thread.Sleep() method sleep more than expected?

Console.Read() reads a character, and then you convert it's ASCII code to int.

This prints 53 if you enter 5:

Console.WriteLine("{0}", Console.Read());

BTW, you multiply 5 by 1000, and then sleep for already multiplied value. So the overall time of sleeping in the loop seems to be 5 * 5 * 1000, not 5 * 1000 ms. Is it intentional?



Related Topics



Leave a reply



Submit