【问题标题】:Understanding the strange behavior of multimedia timer了解多媒体定时器的奇怪行为
【发布时间】:2019-12-09 19:03:57
【问题描述】:

我在我的应用程序 (C# .NET) 中使用多媒体计时器来提高计时器的准确性并实现 1 毫秒的计时器频率。到目前为止,我的应用程序一直运行良好,直到最近它开始出现奇怪的行为。我试图了解我的应用程序出了什么问题。以下是采取的步骤

  1. 定时器频率设置为 1 毫秒,每 1 毫秒调用一次回调
  2. 有 4 个线程,每个线程都创建自己的计时器对象。它们都设置为在 1ms 后调用回调。这些是单独的实例,不共享。
  3. 旧代码执行时间约为 0.3 毫秒。在下一步之前,这一切正常。
  4. 应用程序代码已更改。定时器回调函数现在执行大约需要 1.2 毫秒。这显然是一个问题。 (稍后我将致力于优化代码。但现在我只想了解多媒体计时器的行为)
  5. 只有第一个线程正在调用计时器回调,而对于其他线程,回调仅被调用两次或三次,之后再也不会调用回调。
  6. 看起来对于其他线程,甚至错过了计时器(?)并且它无法赶上。 (每次中断都会丢失)。

能否请您解释一下计时器对象的行为。所有线程实际上都指向同一个计时器对象,因为它是一个进程吗? 为什么其他线程没有调用定时器回调?

【问题讨论】:

  • 如果您提供如何设置多媒体计时器以及使用哪个 .NET 计时器的代码,回答起来会容易得多。否则只能猜测细节。

标签: c# performance timer


【解决方案1】:

多媒体计时器的最大分辨率为 1 毫秒。这会导致可编程中断控制器(在硬件上)每 1ms 触发一次。如果您启动 4 个线程,这些线程都创建了具有 1 毫秒计时的计时器,这并不意味着您每毫秒会收到超过一次的事件。

我鼓励您阅读 MSDN 上的 Why are the Multimedia Timer APIs (timeSetEvent) not as accurate as I would expect? 博客文章。

此处适用的一些引用(强调我的):

MM Timer API 允许开发人员重新编程可编程 机器上的中断控制器 (PIC)。您可以指定新的 定时器分辨率。通常,我们会将其设置为 1 毫秒。这个 是定时器的最大分辨率。 我们无法达到亚毫秒级 准确度。 这种重新编程 PIC 的效果是导致 操作系统更频繁地唤醒。这增加了我们的机会 应用程序将在我们通知时由操作系统通知 指定的。 我说,“增加机会”,因为我们仍然不能 保证我们将实际收到通知,即使 当我们告诉它时,操作系统就开始工作了。

还有:

请记住,PIC 用于唤醒操作系统,以便它可以决定 接下来应该运行什么线程。操作系统使用一些非常复杂的规则来 确定接下来要占用处理器的线程。其中两个 操作系统查看以确定它是否应该运行线程或 不是线程优先级和线程量子。

因此,即使您将分辨率降低到 1 毫秒的最大值,也不能保证您的线程将是被选中执行其工作的线程。

【讨论】:

  • 感谢您的详细回复。我创建 4 个线程的意图不是为了将精度降低到 1 毫秒以下。我期望创建 4 个独立的多媒体计时器线程,它们应该在该线程中每 1 毫秒触发一次事件。我在不同的链接(msdn.microsoft.com/en-us/library/windows/desktop/…)上阅读了多媒体计时器在其自己的线程上运行,并且根据您的链接,某些线程可能因获取 CPU 而饿死。但是如果有 4 个不同的计时器线程,那么这不应该发生。
  • 我认为,就我而言,我只有一个 PIC 线程,所有 4 个计时器事件都由同一线程触发。我仍在阅读有关如何创建 4 个不同线程的信息。 (timeBeginEvent function 打电话?)。我的理解正确吗?
  • 答案似乎没有回答问题。TS 给出了具体条件,并表示在更改之前应用程序按预期工作。之后就没有用了。
【解决方案2】:

我假设您使用了在单个专用线程上运行回调的系统计时器。

然后将系统间隔设置为 1 毫秒。在您进行更改之前,回调需要 0.3 毫秒才能完成,因此 4 个线程的回调需要 4 * 0.3 = 1.2 毫秒才能完成。所以他们设法以 1-2 个时间间隔完成,之后都可以重新开始。

但在您进行更改后,每个回调本身需要 1.2 毫秒。所以我们有从线程 2-4 运行回调的请求和来自线程 1 的另一个请求(因为时间间隔用完了)。之后,它取决于使用的计时器,它将服务哪个请求。事实证明,来自第一个线程的那个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多