【问题标题】:How accurate is Sleep() or sleep()Sleep() 或 sleep() 的准确性如何
【发布时间】:2011-05-06 22:31:54
【问题描述】:

我正在尝试模拟按键按下和按键动作。

例如:2638 毫秒。

SendMessage(hWnd, WM_KEYDOWN, keyCode, 0);
Sleep(2638);
SendMessage(hWnd, WM_KEYUP, keyCode, 0);

你怎么知道它是否真的有效?

【问题讨论】:

  • 线程切换频率约为40毫秒。您的线程通常至少每 3 个线程切换滴答声执行一次。所以你说的是 120 毫秒秒的精确度更坏的情况。这是几年前在一台 XP 机器 P4 HT 上测量的,没有改变 NT_Thread 开关频率。

标签: c winapi sleep windows-xp-sp3


【解决方案1】:

您不会使用此代码,因为准确测量代码执行所需的时间是一项艰巨的任务。

要解决您的问题标题所提出的问题(您真的应该一次问一个问题......)所述功能的准确性由操作系统决定。在 Linux 上,系统时钟粒度为 10 毫秒,因此通过 nanosleep() 的定时进程暂停只能保证精确到 10 毫秒,即使这样也不能保证在您指定的时间内完全休眠。 (见下文。)

在 Windows 上,可以更改时钟粒度以适应电源管理需求(例如,降低粒度以节省电池电量)。见MSDN's documentation on the Sleep function

请注意,使用 Sleep()/nanosleep(),操作系统仅保证进程暂停将持续至少,只要您指定。其他进程的执行总是会延迟您的进程的恢复。

因此,您上面的代码发送的按键事件将比按键事件至少晚 2.638 秒发送,而不是早一毫秒。但事件可能会在 2.7、2.8 甚至 3 秒后发送。 (或者如果一个实时进程控制了 CPU 并且在一段时间内没有放弃控制权,那么很久以后。)

【讨论】:

  • "操作系统只保证进程挂起至少持续你指定的时间。"在 Windows 上,这实际上不是真的。从您发布的 MSDN 链接:“线程可能睡眠时间少于指定的时间长度”。
  • 好点,不知何故我错过了......我会假设线程可能会休眠不少于请求的时间减去当前时钟粒度,但我找不到任何文档。
  • 最近(过去几年)带有 NOHZ 选项的 Linux 内核没有任何最小粒度,除了硬件本身强加的。
  • 我相信这是真的 - 我认为这是链接页面试图通过以下方式表达的内容:“如果 dwMilliseconds 大于一个滴答但小于两个滴答,则等待时间可能介于一到两个滴答之间,等等。”然而,该引用具有误导性,因为它暗示暂停时间有一个上限
  • 对。因此,如果 dwMilliseconds 大于 N 个滴答声但小于 M,则可能是正确的说法,等待将至少为 N 个滴答声。
【解决方案2】:

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

因此对于依赖于用户体验的事情来说是可以的。但是,它绝对不适合实时事物。

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

【讨论】:

    【解决方案3】:

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

    以下线程中的 cmets:

    How to get an accurate 1ms Timer Tick under WinXP

    Sleep Less Than One Millisecond

    【讨论】:

      【解决方案4】:

      命令 Sleep() 将确保线程至少挂起作为参数给出的时间量。操作系统不保证。详细讨论可以参考下面的帖子 how is sleep implemented at OS level?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-31
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 2010-11-27
        相关资源
        最近更新 更多