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

mez*_*oid 16 c# multithreading sleep stopwatch

我遇到了间歇性失败的单元测试,因为经过的时间不是我预期的.

此测试的示例如下:

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);
Run Code Online (Sandbox Code Playgroud)

这种情况大部分时间都过去了,但至少有一次失败,因为:

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

我不明白它怎么可能不到3秒钟.我不知道Thread.Sleep或者Stopwatch是否存在准确性问题?

正如以下一些问题的更新.正在进行单元测试的场景是一个类,它允许一个方法调用一个方法来执行某些操作,如果它失败则等待一秒并调用该方法.上面显示的测试只是对正在发生的事情的近似.

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

Hav*_*ard 15

您的线程与其他线程共享CPU时间.睡眠将在你再次轮到你的时候结束,并且内核注意到睡眠时间已经过去,所以它不那么准确.

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

  • 但是如果它只在内核注意到睡眠时间结束后才结束,它怎么可能比我预期的花费更少的时间?3010ms是可以理解和可接受的,在我的情况下,它在到达要求的时间之前停止...虽然是1-2ms (5认同)
  • 实现可能会在您指定的时间之前几毫秒设置唤醒时间.如果没有,它会*总是*稍后醒来.通过设置更早的时间,它有更好的机会到达某个地方. (2认同)

Spe*_*ort 7

Thread.Sleep不适用于精确唤醒.实际上,Windows体系结构本身并不适用于此类事物.