Thread.Sleep(TimeSpan) 的准确度如何?

发布于 2024-08-03 05:36:13 字数 684 浏览 6 评论 0原文

我遇到过一个单元测试间歇性失败,因为所经过的时间不是我预期的。

此测试的示例如下:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

TimeSpan oneSecond = new TimeSpan(0, 0, 1);

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

stopwatch.Stop();

Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 2999);

大多数情况下都通过,但至少有一次失败,因为:

预期:大于或等于 2999 但是是:2998

我不明白它怎么可能少于3秒。 Thread.Sleep 或秒表是否存在我不知道的准确性问题?

就像下面一些问题的更新一样。正在进行单元测试的场景是一个类,它允许我们调用一个方法来执行某些操作,如果失败,请稍等片刻并调用该方法。上面显示的测试只是所发生情况的近似值。

假设我想调用一个方法 DoSomething()...但是如果 DoSomething() 抛出异常,我希望能够重试调用它最多 3 次,但每次尝试之间等待 1 秒。在本例中,单元测试的目的是验证当我们请求 3 次重试且每次重试之间等待 1 秒时,所花费的总时间是否大于 3 秒。

I've come across a unit test that is failing intermittently because the time elapsed isn't what I expect it to be.

An example of what this test looks like is:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

TimeSpan oneSecond = new TimeSpan(0, 0, 1);

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

stopwatch.Stop();

Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 2999);

Most of the time this passes but it has failed on at least on one occasion failed because:

Expected: greater than or equal to 2999
But was: 2998

I don't understand how it could possibly be less than 3 seconds. Is there an accuracy issue with Thread.Sleep or maybe Stopwatch that I'm not aware of?

Just as an update to some of the questions below. The scenario that is being unit tested is a class that allow's one to call a method to perform some action and if it fails wait a second and recall that method. The test shown above is just an approximation of what is happening.

Say I wanted to call a method DoSomething()...but in the event of an exception being thrown by DoSomething() I want to be able to retry calling it up to a maximum of 3 times but wait 1 second between each attempt. The aim of the unit test, in this case, is to verify that when we requested 3 retries with 1 second waits between each retry that the total time taken is greater than 3 seconds.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回忆追雨的时光 2024-08-10 05:36:13

您的线程正在与其他线程共享 CPU 时间。一旦轮到你,睡眠就会结束,内核注意到睡眠时间已经过去,所以它不那么准确。

CPU负载、进程优先级、并发线程数,甚至来自其他进程的线程数,都会对其产生影响。

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.

野鹿林 2024-08-10 05:36:13

Thread.Sleep 不适用于精确唤醒。事实上,Windows 架构本身并不是为这种事情设计的。

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

国产ˉ祖宗 2024-08-10 05:36:13

快速实验,我注意到像这样的代码片段...

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

多次显示相同的数字,然后跳转到多次显示的新数字,等等。这些数字组之间的间隙始终为 15.625ms,我注意到是 1000 / 64。

看起来 Windows 计时器的粒度为 1/64一秒钟。如果你需要比这更好的东西,那么我能理解你的痛苦,但这就是你必须适应的框架。 (Windows 不是硬实时操作系统,也没有声称是)。

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).

幻想少年梦 2024-08-10 05:36:13

线程休眠和定时/节流是非常不同的事情,应该适当对待。休眠线程是一项通用任务,允许系统为其他线程和进程提供执行的机会,而无需具体说明。另一方面,限制应用程序或调度需要精确计时的任务应使用显式计时器来执行。

请记住,如果您需要时间精确的进程或同步,则使用 Windows 中的正常进程将很难实现这一目标。您需要利用 Windows 实时优先级来成功实现准确的计时或限制,因为如果任何线程被另一个线程抢占,Windows 可以随时休眠任何线程。

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.

错々过的事 2024-08-10 05:36:13

在一个我想要睡眠至少 x 毫秒的应用程序中,我使用了一些类似于以下内容的代码:

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();
}

对于 Thread.Sleep 的准确度,它根本不准确。我认为分辨率约为 10 毫秒。除了“大约”这么长时间之外,它不能保证做任何事情。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文