【问题标题】:Which timer class to use for a metronome?哪个计时器类用于节拍器?
【发布时间】:2016-03-04 18:51:52
【问题描述】:

.net 框架有很多方法可以使用计时器,但是对于节拍器,我应该使用哪一种呢?

我尝试了所有这些计时器,但没有一个足够准确以供我使用(它们的分辨率不能低于 15 毫秒)。

System.Windows.Forms.Timer
System.Web.UI.Timer
System.Diagnostics.Stopwatch   
System.Timers.Timer
System.Threading.Timer

对于我的节拍器课程,我需要 Ticks 可靠、恒定、无漂移。

我在 MSDN 上找到了这个实现:https://msdn.microsoft.com/en-us/library/aa964692(v=vs.85).aspx 使用“coredll.dll”

另一种解决方案是实现这些原生方法:

[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")]
internal static extern UInt32 TimeSetEvent(UInt32 msDelay, UInt32 msResolution, MultimediaTimerCallback callback, ref UInt32 userCtx, UInt32 eventType);

[DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent")]
internal static extern void TimeKillEvent(UInt32 uTimerId);

在 windows 上设置分辨率低于 5 毫秒的计时器的最佳方法是什么?

编辑

我在.net(法语)中发现了这个关于计时器的非常有趣的链接: http://www.e-naxos.com/Blog/post/NET-et-ses-timers-Prise-de-tete-ou-reelle-utilite-.aspx

【问题讨论】:

  • 你试过 DispatcherTimer 吗?
  • DispatcherTimer 的分辨率和其他的一样,最好的是System.Diagnostics.StopwatchDispatcherTimer 用于操作对象 UI,它不准确,因为在 Dispatcher 堆栈上进行了评估,还是我错了?
  • 似乎合法。我只是经常使用这个,因为它似乎是最适合我需要的功能。
  • timeSetEvent() 几乎就是为此而设计的,但是您还必须调用 timeBeginPeriod() 以使分辨率足够好。

标签: c# timer


【解决方案1】:

您应该为此使用Multimedia Timer

多媒体计时器服务允许应用程序安排计时器事件 具有硬件可能的最大分辨率(或精度) 平台。这些多媒体计时器服务允许您安排计时器 比其他计时器服务更高分辨率的事件。

这些计时器服务对于需要 高分辨率时序。例如,一个 MIDI 音序器需要一个 高分辨率计时器,因为它必须保持 MIDI 事件的节奏 在 1 毫秒的分辨率内。

有各种 C# 库可用于帮助使用这些库。

例如:http://www.codeproject.com/Articles/5501/The-Multimedia-Timer-for-the-NET-Framework

【讨论】:

    【解决方案2】:

    更新

    正如@Guillaume 在 cmets 中指出的那样,StopWatch 似乎可以作为性能计数器的托管替代品。所以我想你应该使用它


    如果你想要精确,我肯定会使用原生的QueryPerformanceCounter,但是你链接的是.NET Compact Framework (coredll)...对于Windows,你需要使用kernel32

    我在 C#on this link 上有一个 非常老的 (2003) 计时器实现 QueryPerformanceCounter。它依赖于其他模块,但应该很容易删除(我认为唯一的依赖是在 Initialize() 方法上记录异常,但我已经有 13 年没有接触过该代码了......它是运行在 C# 1.0 上的.NET 1.0)。

    请注意,这不会发出事件,您需要处理自己的循环并检查经过的时间。

    也就是说,低于 5 毫秒是一个非常低的精度,您不应该依赖任何以 5 毫秒精度工作的东西(只要您的计算机正在做其他事情,甚至垃圾收集您自己的应用程序)。如果您的节拍器应用程序发出声音,除非它是 Windows 10,否则您可能已经有超过 5 毫秒的延迟(Windows 10 低延迟标准声音驱动程序堆栈对整数数据有 4.5 毫秒,对浮点数据有 16 毫秒)。

    【讨论】:

    • 来自StopWatch 文档:“Frequency 字段和 GetTimestamp 方法可用于代替非托管 Win32 API QueryPerformanceFrequency 和 QueryPerformanceCounter。” msdn.microsoft.com/en-us/library/…
    • @Guillaume 是的,当我编写那个计时器时,它似乎不可用......这些天我不使用任何高分辨率计时(虽然我确实使用秒表来测量功能)。 ..所以肯定,它应该是一个替代品。我会用那句话更新
    • 感谢您的帮助,非常有趣的帖子。
    • 使用秒表是个坏主意,你只能通过不断地轮询来观察一个间隔。燃烧 100% 核心。这为操作系统提供了一个很好的理由,在线程耗尽其量子之后将其放入狗屋一段时间。产生 45 毫秒或更长的延迟。在临时测试程序中不明显,在机器忙时发生。
    • @HansPassant 我过去曾通过轮询非阻塞循环(在轮询线程上使用 Thread.Sleep)来使用性能计数器。可能不是最好的方法(这是很久以前的事了,以后再也不需要了),但是是的,我明白你的意思
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2014-06-16
    • 2018-03-09
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多