我在代码中使用Sleep(500)
并使用getTickCount()
来测试时间。我发现它的成本约为515ms,超过500.有人知道为什么会这样吗?
答案 0 :(得分:63)
因为Win32 API的Sleep
不是高精度睡眠,并且具有最大粒度。
获得精确睡眠的最佳方法是睡眠少一点(约50毫秒)并进行忙碌等待。要找到您需要忙碌的准确时间,请使用timeGetDevCaps
获取系统时钟的分辨率,然后乘以1.5或2以保证安全。
答案 1 :(得分:30)
sleep(500)
保证的睡眠时间至少 500毫秒。
但它可能会睡得更久:没有定义上限。
在您的情况下,调用getTickCount()
时还会有额外的开销。
您的非标准Sleep
功能可能表现得与众不同;但我怀疑是否保证了准确性。要做到这一点,你需要特殊的硬件。
答案 2 :(得分:18)
正如您可以在the documentation中阅读,WinAPI函数GetTickCount()
仅限于系统计时器的分辨率,通常在10毫秒到16毫秒的范围内。
要获得更准确的时间测量,请使用函数GetSystemDatePreciseAsFileTime
此外,您不能依赖Sleep(500)
睡眠完全 500毫秒。它会暂停的线程至少 500毫秒。一旦有可用的时隙,操作系统将继续该线程。当操作系统上运行许多其他任务时,可能会有延迟。
答案 3 :(得分:13)
一般情况下,睡眠意味着你的线程进入等待状态,并且在500ms之后,它将处于" runnable"州。然后OS调度程序根据当时可运行进程的优先级和数量选择运行某些。因此,如果你有高精度睡眠和高精度时钟,那么它仍然是一个至少500毫秒的睡眠,而不是500毫秒。
答案 4 :(得分:12)
与其他答案一样,Sleep()
的准确性有限。实际上, no 实现类似Sleep()
的功能可以完全准确,原因如下:
实际调用Sleep()
需要一些时间。虽然旨在实现最大准确度的实现可以尝试测量并补偿这种开销,但很少有人费心。 (并且,无论如何,由于许多原因(包括CPU和内存使用),开销可能会有所不同。)
即使Sleep()
使用的基础计时器在发射所需的时间,也无法保证您的进程在唤醒后会立即重新安排。您的进程在睡眠时可能已被换出,或者其他进程可能会占用CPU。
操作系统可能无法在请求的时间唤醒您的进程,例如因为计算机处于挂起模式。在这种情况下,您的500毫秒Sleep()
电话很可能最终需要几个小时或几天。
此外,即使Sleep()
非常准确,您想要在睡眠后运行的代码也不可避免地会消耗一些额外的时间。
因此,为了定期执行某些操作(例如重绘屏幕或更新游戏逻辑),标准解决方案是使用补偿 Sleep()
循环。也就是说,您维护一个定期递增的时间计数器,指示下一个动作应何时发生,并将此目标时间与当前系统时间进行比较,以动态调整您的睡眠时间。
需要特别注意处理意外的大时间跳跃,例如:如果计算机暂时被怀疑或计数器计数器缠绕在一起,以及处理操作的时间比下一次操作之前的时间更长,导致循环滞后。
这是一个应该处理这两个问题的快速示例实现(伪代码):
int interval = 500, giveUpThreshold = 10*interval;
int nextTarget = GetTickCount();
bool active = doAction();
while (active) {
nextTarget += interval;
int delta = nextTarget - GetTickCount();
if (delta > giveUpThreshold || delta < -giveUpThreshold) {
// either we're hopelessly behind schedule, or something
// weird happened; either way, give up and reset the target
nextTarget = GetTickCount();
} else if (delta > 0) {
Sleep(delta);
}
active = doAction();
}
这将确保doAction()
平均每<{1}}毫秒调用一次,至少只要它不会持续消耗更多的时间,并且只要没有大的时间跳跃发生。连续调用之间的确切时间可能会有所不同,但任何此类变化都将在下一次调整时得到补偿。
答案 5 :(得分:2)
默认计时器分辨率很低,您可以根据需要增加时间分辨率。 MSDN
PCFunc = Func.PCFunc ()
答案 6 :(得分:1)
代码可能需要像#34; sleep&#34;:
这样的函数有两个一般原因它有一些任务可以在将来至少有一段距离的任何时间执行。
它有一些任务应尽可能在将来的某个时刻尽可能地进行。
在一个好的系统中,应该有单独的方式发出这类请求; Windows使第一个比第二个更容易。
假设系统中有一个CPU和三个线程,这些线程都很有用 工作到午夜前一秒钟,其中一个主题说它不会有 任何有用的事情至少一秒钟。那时,系统会 将执行权交给剩下的两个线程。如果,在午夜前1ms, 其中一个线程决定它至少没有任何有用的东西 第二,系统将控制切换到最后剩余的线程。
当午夜滚动时,原始的第一个线程将可用 运行,但由于当前正在执行的线程将只有CPU 那时的毫秒,原始的第一个没有特别的原因 线程应该被认为更多&#34;值得&#34; CPU时间比其他线程 刚得到控制权。由于切换线程不是免费的,因此操作系统可能非常自由 确定当前拥有CPU的线程应该保留它直到 它会阻塞某些东西或耗尽整个时间片。
如果有一个版本的&#34; sleep&#34;那可能会很好。哪个更容易使用 比多媒体计时器,但会要求系统给线程a 当它有资格再次运行或更好时,临时优先级提升 睡眠的变化&#34;睡眠&#34;这将指定最短时间和优先级 - 升压&#34;时间,适用于需要在特定时间窗口内执行的任务。但是,我不知道任何可以轻松地以这种方式工作的系统。