【问题标题】:Pausing the thread in C# for more accurate time than Thread.Sleep - what would be the best approach?在 C# 中暂停线程以获得比 Thread.Sleep 更准确的时间 - 最好的方法是什么?
【发布时间】:2018-11-07 16:54:29
【问题描述】:

我有这个代码:

while(MouseKeyboardStateTest.Keyboard.IsKeyDown(Keys.Space))
{
    Keyboard.KeyPress(Keys.A);
    Thread.Sleep(asChecker.currentDelay);
    for (int i = 0; i <= asChecker.currentMouseClicks; i++)
    {
        Mouse.PressButton(Mouse.MouseKeys.Right);
        Thread.Sleep(globalMouseDelay);
    }
}

它工作正常,问题是 - Thread.Sleep 不准确,延迟并不总是相同。 有没有其他方法可以解决这个问题,使其至少精确到 10 毫秒?

【问题讨论】:

  • 完全尽可能准确。操作系统线程调度程序仅查找准备好在“心跳”(时钟滴答中断)处运行的线程。它通常每秒滴答 64 次。当您打开浏览器时,往往是 100 次。您不能假设您的线程在睡眠时间到期时实际上获得了处理器,它必须与也需要服务的其他线程竞争。使用 Thread.Priority 可以帮助获得不公平的份额。要保证它将是 10 毫秒而不是 15.625,您需要调用 timeBeginPeriod()。

标签: c# sleep pause


【解决方案1】:

根本不要使用Thread.Sleep

将表单的KeyPreview设置为true,并使用表单的按键事件。

这将允许您在没有延迟和没有循环冻结 UI 的情况下获得关键事件的通知。

另请参阅 this answerWinforms : Intercepting Mouse Event on Main Form first, not on Controls

您也可以改用游戏 API。这些使您可以非常快速地对鼠标和按键事件做出反应,并且不依赖于控件。它们还允许您检测同时按下的按键。


由于您不是在 UI 中执行此操作(根据您的评论),我建议采用不同的方法:

在游戏中,您通常使用尽可能快地循环的游戏循环,没有任何Thread.Sleep 延迟。在每个循环中,您检查输入(键盘、鼠标、操纵杆)的当前状态并更新游戏状态并相应地显示。

在每个循环中,使用DateTime.UtcNow(比DateTime.Now 快)保存当前时间,并检查自某个动作发生以来经过的时间,以了解是否已达到所需的延迟。

如果DateTime 不够准确,请使用StopWatch 类。见:Precision and accuracy of DateTime

【讨论】:

  • 我没有使用任何UI,延迟是存在的,因为它在游戏中做动作,它需要有一定的延迟。
  • 由于您重新打开并回答了问题,请用更好的标题编辑问题。就目前而言,提出这个问题的人可能会遇到与您在此处回答的问题完全不同的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 2014-10-04
  • 1970-01-01
相关资源
最近更新 更多