我能保证 Sleep() 不会休眠超过 10 毫秒吗?

Can I guarantee that Sleep() would not sleep for more than 10 ms?

我知道 Sleep() 不准确,但是有没有办法让它休眠不超过 10 毫秒(即只在 1 毫秒到 10 毫秒之间休眠)?还是 Sleep(1) 已经保证了?

没有办法保证。

这就是 real time OS 的用途。

一般情况下,如果您的 OS 没有遇到高负载,睡眠会非常准确,但随着负载的增加,它会变得更加不准确。

没有。 或者,是的,取决于你的观点。

根据the documentation

After the sleep interval has passed, the thread is ready to run. If you specify 0 milliseconds, the thread will relinquish the remainder of its time slice but remain ready. Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses. For more information, see Scheduling Priorities.

这意味着问题不在于 Sleep。相反,当 Sleep 结束时,您的线程可能仍需要等待才能再次激活。

如果你真的想要保证时间,你根本不会使用 Windows。

为了回答您的问题,Sleep() 不提供任何保证睡眠时间上限的方法。

在windows中,这是因为Sleep()放弃了线程的时间片,不保证系统调度器会调度休眠线程(即分配另一个时间片)立即执行睡眠时间到后。这取决于竞争线程的优先级、调度策略等。

实际上,实际的休眠间隔在很大程度上取决于系统上有哪些其他程序运行、系统配置、其他程序是否正在访问慢速驱动器等

对于负载较轻的系统,可以肯定 Sleep(1) 在任何现代(GHz 频率 CPU 或更高)上会休眠 1 到 2 毫秒。但是,你的程序遇到更大的延迟也不是没有可能。

对于负载很重的系统(许多其他程序正在执行,使用 CPU 和计时器资源),可以肯定您的程序将经历比 1 毫秒甚至超过 10 毫秒大得多的延迟。

简而言之:没有保证。

Sleep 不保证。

我知道的唯一方法是让一个线程等待一个快速计时器事件,并每 10 毫秒左右释放一个同步对象。

您将向此 "wait server task" 传递一个信号量,它将在下一个计时器滴答时释放它,从而为您提供 0 到 10 毫秒之间的响应时间。

当然,如果您想要极高的精度,则必须将此线程的优先级提高到可能抢占它的其他任务之上,并且无论如何您仍可能被系统进程 and/or 中断处理程序抢占,这会给你的计时器增加一些噪音。

您不能指望 10 毫秒,这太低了。 Sleep() 准确性受以下因素影响:

  • 时钟节拍中断频率。通常,处理器往往处于静止状态,不消耗任何功率并由 HLT 指令关闭。它对世界来说是死的,没有意识到时间在流逝,也没有意识到你的睡眠间隔已经到期。芯片组产生的周期性硬件中断将其唤醒并使其再次关注。默认情况下,此中断每秒生成 64 次。或者每 15.625 毫秒一次。

  • 线程调度程序在每个时钟中断时 运行s。它会注意到您的睡眠间隔已过期,它会将线程放回 ready-to-运行 状态。并提高其优先级,使其更有可能获得处理器核心。当没有其他具有更高优先级的线程准备好 运行.

  • 时,它将这样做

对于第 2 颗子弹,你无能为力,你必须与其他人竞争并分享你的公平份额。如果该线程进行大量休眠和少量计算,那么要求超过您的公平份额并不是不合理的,请调用 SetThreadPriority() 来提高您的基本优先级并使您的睡眠间隔更有可能准确。如果这还不够好,那么获得足够高的优先级并始终击败其他人的唯一方法是编写 ring 0 代码,一个驱动程序。

您可以弄乱第一个项目符号,这样做很常见。这也是许多程序员认为默认精度为 10 毫秒的原因。或者,如果他们使用 Chrome 可能是 1 毫秒,则该浏览器会将中断率提高到天价。这是一件相当不合理的事情,对功耗不利,除非你的业务是让你的移动操作系统产品看起来不错 :)

在需要使睡眠间隔足够短之前调用 timeBeginPeriod,完成后调用 timeEndPeriod()。如果您需要低于 1 毫秒,请使用 NtSetTimerResolution()。