How accurate is Thread.Sleep(TimeSpan)?

蹲街弑〆低调 提交于 2019-11-26 16:40:42

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.

Thread.Sleep is not intended to be used for precision waking. Really, windows architecture itself is not intended for this kind of thing.

Quickly experimenting, I notice that a code fragment like...

do { Debug.WriteLine( DateTime.Now.TimeOfDay.TotalMilliseconds.ToString() ); } while ( 1 );

displays the same number multiple times, then jumps to a new number displayed multiple times, etc. The gap between these sets of numbers is consistently 15.625ms which I notice is 1000 / 64.

Looks like Windows timers have a granularity of 1/64th of a second. If you need better than that then I feel your pain, but that's the framework you have to fit within. (Windows isn't a hard real-time OS and doesn't claim to be).

Thread sleeping and timing/throttling are very different things, and should be treated appropriately. Sleeping a thread is a general task, allowing the system to give other threads and processes the chance to execute without being specific about it. On the other hand, throttling an application or scheduling tasks that need accurate timing should be performed with an explicit timer.

Keep in mind, if you need time-accurate processes or synchronization, you will have a hard time achieving that with a normal process in windows. You would need to utilize windows realtime priorities to successfully achieve accurate timing or throttling, as windows can sleep any thread at any time if it is preempted by another thread.

In one application where I wanted to sleep for atleast x milliseconds, I used some code similar to:

public void Sleep(int milliseconds)
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    while (stopwatch.ElapsedMilliseconds < milliseconds)
    {
        int timeout = milliseconds - stopwatch.ElapsedMilliseconds;
        Thread.Sleep(timeout >= 0 ? timeout : 0);
    }

    stopwatch.Stop();
}

In response to how accurate Thread.Sleep is, it's not accurate at all. I think the resolution is somewhere around 10ms. It isn't guaranteed to do much of anything except 'approximately' this long.

Maybe you shoudn't rely on the time bias to find out if you where successfully. Better count your number of tries and evaluate against this:

int tries;

for(tries=0; tries<3; tries++)
{
    Thread.Sleep(oneSecond);
}

Assert.GreaterOrEqual(tries, 3);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!