了解多媒体计时器的奇怪行为
我在我的应用程序(C#.NET)中使用多媒体计时器来提高计时器的准确度并达到1 ms的计时器频率。 到目前为止,我的应用程序一直运行良好,直到最近它开始表现得很奇怪。 我试图了解我的申请有什么问题。 以下是采取的步骤
- 定时器频率设置为1 ms,每1ms调用一次回叫
- 有4个线程,每个线程创建自己的计时器对象。 它们都设置为在1ms后调用回调。 这些是个别实例,不共享。
- 旧的代码执行时间约为0.3毫秒。 这个工作正常,直到下一步。
- 应用程序代码已更改。 定时器回调函数现在需要大约1.2 ms才能执行。 这显然是个问题。 (我将在稍后优化代码。但现在我只想了解多媒体计时器行为)
- 只有第一个线程正在调用定时器回调,而对于其他线程,回调只被调用两次或三次,之后永远不会调用回调。
- 看起来对于其他线程,计时器甚至错过了(?),它无法赶上。 (它错过了每次中断)。
你能解释一下计时器对象的行为吗? 所有线程实际上都指向同一个计时器对象,因为它只有一个进程吗? 为什么其他线程没有调用定时器回调?
多媒体计时器的最大分辨率为1毫秒。 这导致可编程中断控制器(在硬件上)每1ms发射一次。 如果你启动了4个线程,所有线程都创建了1ms时间的计时器,这并不意味着你将每毫秒获得一次以上的事件。
我鼓励您阅读为什么多媒体计时器API(timeSetEvent)不如我预期的那样准确? MSDN上的博客文章。
这里适用的一些引用(强调我的):
MM Timer API允许开发人员重新编程机器上的可编程中断控制器(PIC)。 您可以指定新的计时器分辨率。 通常,我们将其设置为1毫秒。 这是计时器的最大分辨率。 我们无法获得亚毫秒精度。 这种重新编程PIC的效果是使OS更频繁地唤醒。 这增加了我们在指定时操作系统通知应用程序的机会。 我说,“增加机会”因为我们仍然不能保证我们实际上会收到通知,即使操作系统在我们告诉它时工作。
和:
请记住,PIC用于唤醒操作系统,以便它可以决定接下来应该运行什么线程。 操作系统使用一些非常复杂的规则来确定接下来占用处理器的线程。 操作系统查看是否应该运行线程的两件事是线程优先级和线程量。
因此,即使您将分辨率降低到最大1ms,也不能保证您的线程将是选择执行其工作的线程。