.NET 中的精确计时

Posted

技术标签:

【中文标题】.NET 中的精确计时【英文标题】:Precision timing in .NET 【发布时间】:2009-04-27 22:10:13 【问题描述】:

我刚刚看到this question,其中一个答案表明System.Diagnostics.Stopwatch 应该只用于诊断性能,而不是在生产代码中。

在这种情况下,在 .NET 中获得精确计时的最佳方法是什么?我目前正处于使用NAudio 的MIDI 输出功能构建一个非常简单的MIDI 音序器的早期阶段。我希望能够以尽可能少的抖动将 MIDI 消息发送到(比如说)1/10 秒。这是可行的吗,还是上下文切换之类的事情会毁了我的一天?

我目前在控制台应用程序中有一些代码,它连续调用Stopwatch 并在以 150bpm 生成 1/16 音符流时计算抖动。在这种情况下,抖动非常低。不过,我将把它移到另一个线程,所以我不知道是否会保持这种情况。

【问题讨论】:

【参考方案1】:

如果您不介意 P/Invoke,可以使用 QueryPerformanceCounter:http://www.eggheadcafe.com/articles/20021111.asp

【讨论】:

+1。性能计数器将为您提供您能找到的最精确、最轻的计数器。它不像其他实现那样简单。 据我了解,Stopwatch 使用 QueryPerformanceCounter(如果有)。我没有反对 QPC 并且之前在 C++/Win32 应用程序中使用过它,但是我不知道 CLR 的较低级别发生了什么,所以想知道是否有更好的方法。 你说得对,秒表确实使用 QueryPerformanceCounter - 我没有意识到。阅读了另一个问题后,我认为有人建议不要在生产中使用 Stopwatch 的唯一原因是它会带来一些开销,但我想这非常小,而且很容易测量。【参考方案2】:

您还可以使用本机流式传输 MIDI API。我不认为它在 NAudio 中,但您可以查看 C# Midi Toolkit 以查看它是否支持它。否则,您有两个示例说明如何执行本机 MIDI API P/Invoke,并且可以自己动手...

【讨论】:

NAudio 中有一些流媒体 MIDI API 的包装器,但它们还没有完成。不过,可能会为您指明正确的方向【参考方案3】:

Windows multimedia timer 声明它允许“应用程序以硬件平台可能的最大分辨率(或精度)来安排计时器事件。”

它用作示例的应用程序是 MIDI 音序器。

【讨论】:

【参考方案4】:

我是DryWetMIDI 的作者。该库具有播放功能,可在 WinMM 高精度计时器的帮助下工作。 Timer 被封装到 MidiClock 类中,因此您可以使用它来驱动您的 MIDI 操作:

var midiClock = new MidiClock(true, new HighPrecisionTickGenerator(), TimeSpan.FromMilliseconds(1));
midiClock.Ticked += OnTick;

OnTick 将使用此代码每 1 毫秒调用一次。

【讨论】:

以上是关于.NET 中的精确计时的主要内容,如果未能解决你的问题,请参考以下文章

swift iOS / OSX / Swift中的精确计时

使用 AudioUnit 的精确计时器

C++中如何精确计时

我可以精确计时重叠的 ReadFileEx 操作吗?

Js倒计时代码精确到毫秒。

在C语言中如何实现精确计时