【问题标题】:.net thread.sleep inaccurate.net thread.sleep 不准确
【发布时间】:2021-07-09 01:27:32
【问题描述】:

我快疯了!! 我通过 gsm 和语音规范发送音频,我必须发送语音数据包,然后等待 20 毫秒才能获得正常语音。我使用 system.threading.thread.sleep(20)。但是,我注意到声音很慢。但是当我运行另一个不同的应用程序时,声音变得正常。

经过一些调试,我发现 system.Threading.Thread.Sleep(20) 需要 31 毫秒,但是如果我运行另一个不同的应用程序,Thread.Sleep(20) 将始终准确。

为了使线程准确地休眠 20 毫秒并且同时不影响 PC 性能,我可以使用哪些其他替代方法。

谢谢,

【问题讨论】:

  • 如果您想获得准确的结果,您将不得不旋转等待,这对 PC 性能不利。
  • 睡眠精度由时钟中断率决定,默认为每秒 64 次。每 15.625 毫秒一次。所以 Sleep(20) 直到两个滴答声过去后才能完成,2 x 15.625 = 31.25 毫秒。可以更改中断率,浏览器或媒体播放器很容易这样做。他们打电话给timeBeginPeriod(),你也可以。
  • 请注意,如果有任何问题,提高时钟中断率会对电池寿命产生重大影响。 wp.me/p1fTCO-kJ
  • 亲爱的汉斯,你的计算是正确的。我得到的是 31 毫秒,一段时间后是 32 毫秒,然后是 31 毫秒。当我打开 Firefox 时,它会精确到 20 毫秒,读取 500 个读数。现在提出问题来解决这个问题。我应该将 timebeginPeriod 设置为什么?
  • 汉斯...你做到了..非常感谢:)。它就像魔术一样工作。我使用了 timeBeginPeriod(10) ,一切正常。请建议如何将您的帖子设置为答案

标签: .net multithreading sleep


【解决方案1】:

Sleep(20) 表示睡眠至少 20 毫秒。基本上,它会挂起线程并且不会在指定的延迟内恢复调度。之后,仍然必须安排线程以实际恢复运行。取决于正在运行的其他线程,可能会立即或稍后运行。这里没有任何保证。

documentation 大声疾呼:

系统时钟以称为时钟分辨率的特定速率滴答作响。 实际超时可能与指定的超时不完全一致,因为 指定的超时将调整为与时钟滴答相一致。 有关时钟分辨率和等待时间的更多信息,请参阅 睡眠功能主题。此方法从 Windows 系统 API。

【讨论】:

  • 那么,你推荐使用什么?我看到一个 Java 程序,它使用 Thread.Sleep (20) & 似乎工作得很好。这与编程语言或操作系统有关吗? & 对于 .net ,在时间准确性和 CPU 利用率之间取得良好平衡的最佳解决方案是什么。谢谢。
  • 我希望 Java 应用程序具有相同的行为 - 至少在 Windows 上是这样。事实上,Java 文档对超时有相同的说明。 docs.oracle.com/javase/tutorial/essential/concurrency/…
  • 我还有一个问题,当我使用 winmme timeBegion 时,它就像 x 32 位系统中的魅力一样。但在 x 64 位系统上,它给出了奇怪的行为。请建议如何在 64 个系统上克服这个问题。
【解决方案2】:

如前所述,准确的计时通常需要一个不会被时间分割的线程/进程,为此,您必须Spin 而不是Sleep

选项 1

如果您想要绝对准确,我会使用带秒表的专用高优先级线程。

bool running = true;
Thread t = new Thread(() =>
{
    Stopwatch sw = Stopwatch.StartNew();
    while (running)
    {
        if (sw.ElapsedMilliseconds >= 20)
        {
            RunCode();
            sw.Restart();
        }
    }
}) { Priority = ThreadPriority.Highest, IsBackground = true };

t.Start();

// ...

running = false;
t.Join();

选项 2

更精简了,不会在不同的线程上运行,但仍会旋转。

while (true) 
{
    SpinWait.SpinUntil(() => false, TimeSpan.FromMilliseconds(20));
    RunCode();
}

选项 3

一些开源的高分辨率计时器代码。例如https://gist.github.com/HakanL/4669495

【讨论】:

  • 我尝试了第一个选项和第二个选项,但似乎我做错了什么。秒表不提供准确的数据。我找到了时钟中断更改示例解决方案。非常感谢您的大力支持。真的很感激。
  • 抱歉,很可能 1 和 2 不能直接开箱即用 - 我没有测试它们,应该补充一下 :) 没问题。
  • 亲爱的詹姆斯,非常感谢您的大力支持。真的很感激。
猜你喜欢
  • 1970-01-01
  • 2020-12-18
  • 2010-11-21
  • 2011-02-19
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
相关资源
最近更新 更多