Sleep()或sleep()的精确度有多高?

4
我正在尝试模拟按下和松开键的操作。
例如:2638毫秒。
SendMessage(hWnd, WM_KEYDOWN, keyCode, 0);
Sleep(2638);
SendMessage(hWnd, WM_KEYUP, keyCode, 0);

如果真的有效,您将如何知道?


线程切换频率约为40毫秒。您的线程通常至少在每3个线程切换滴答中执行一次。因此,您谈论的是最坏情况下120毫秒的精度。这是在几年前的XP机器P4 HT上测量的,并且没有更改NT_Thread切换频率。 - CodingBarfield
4个回答

6
您不会用这段代码来准确地测量代码执行的时间,因为准确地测量代码执行时间是一项困难的任务。
要回答您的问题标题(您真的应该一次只问一个问题...),这些函数的精度由操作系统决定。在Linux上,系统时钟粒度为10毫秒,因此通过nanosleep()进行定时进程挂起仅保证精度为10毫秒,即使如此,也不能保证它会恰好休眠指定的时间。(见下文。)
在Windows上,时钟粒度可以更改以适应电源管理需求(例如,减少粒度以节省电池电力)。请参阅MSDN关于Sleep函数的文档
请注意,使用Sleep()/nanosleep(),操作系统仅保证进程挂起至少持续您指定的时间。其他进程的执行始终可能延迟您的进程的恢复。
因此,你上面的代码发送的按键松开事件将比按键按下事件至少晚2.638秒发送,而不会更早一毫秒。但是,事件可能会在2.7、2.8甚至3秒后发送。(如果实时进程占用了CPU并且未释放控制权,则可能会晚得多。)

6
操作系统只保证进程的暂停时间至少与您指定的时间一样长。但在Windows上,实际情况并非如此。根据您发布的MSDN链接,线程的睡眠时间可能会比指定的时间短。 - user200783
好的观点,不知怎么错过了...我会假设线程可能休眠的时间不少于请求时间减去当前时钟粒度,但我在任何文档中都找不到相关信息。 - cdhowie
1
近几年带有NOHZ选项的Linux内核除了硬件本身施加的最小粒度外,没有任何最小粒度。 - caf
我相信这是正确的 - 我认为链接页面试图通过以下方式来表达:“如果dwMilliseconds大于一个时钟周期但小于两个,则等待时间可以在一到两个时钟周期之间任何位置,依此类推。” 然而,该引用是误导性的,因为它暗示了悬挂时间存在上限 - user200783
1
好的。因此,可以说如果dwMilliseconds大于N个滴答但小于M个滴答,则等待时间至少为N个滴答。 - cdhowie

1

Sleep 根据标准的 Windows 线程调度工作。它的精度大约为 20-50 毫秒。

因此,对于用户体验相关的事情来说还可以接受。但是对于实时性要求高的事情来说绝对不合适。

除此之外,还有更好的方法来模拟键盘/鼠标事件。请参见 SendInput


0

0

当请求的延迟时间短于下一个中断发生的剩余时间时,sleep()函数将在所需延迟之前返回。但这只是指出您想要睡眠的时间比系统当前支持的时间短。建议将多媒体定时器资源设置为更高的中断频率,以获得更好的匹配观察到的睡眠延迟与所需延迟。

以下线程中的评论:

如何在WinXP下获得准确的1ms计时器滴答声

睡眠少于一毫秒


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接