以高分辨率间隔/计时器提升事件

我想使用c#使用最高分辨率计时器。 例如,我想每11个时钟提出一个事件(我听说嘀嗒是pc中最高的计数器)。 我试过计时器,发现最小经过时间以毫秒为单位。 我看了秒表,但秒表不会引发事件。

谢谢。

使用多媒体计时器应该每秒给你大约1000个事件。 此代码应该可以帮助您。

public delegate void TimerEventHandler(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2); ///  /// A multi media timer with millisecond precision ///  /// One event every msDelay milliseconds /// Timer precision indication (lower value is more precise but resource unfriendly) /// delegate to start /// callBack data  /// one event or multiple events /// Dont forget to call timeKillEvent! /// 0 on failure or any other value as a timer id to use for timeKillEvent [DllImport("winmm.dll", SetLastError = true,EntryPoint="timeSetEvent")] static extern UInt32 timeSetEvent(UInt32 msDelay, UInt32 msResolution, TimerEventHandler handler, ref UInt32 userCtx, UInt32 eventType); ///  /// The multi media timer stop function ///  /// timer id from timeSetEvent /// This function stops the timer [DllImport("winmm.dll", SetLastError = true)] static extern void timeKillEvent( UInt32 uTimerID ); 

运行它们后,请停止这些计时器。 它们对你的系统非常沉重*。 捕获所有exception并且不要让它们逃脱您的事件处理程序。

*启动超过5个计时器将严重减慢大多数系统! 在事件处理程序中尽可能少地执行代码,并确保执行代码快于1毫秒或遇到严重问题。 我每隔10-50个刻度开始一个代表,以增加标签显示。

Thread.Sleep上发生的正常线程切换将使一个线程槽没有代码,并且将花费大约40毫秒。 您还可以通过一些NT内核调用来增加线程切换频率,但请不要这样做。

首先,你需要意识到, 由于硬件和软件都有限制,在计算机上进行精确计时是非常困难的,如果不是不可能的话。 好消息是这种精度很少是必要的。 十蜱是一个非常少的时间。 在这个时间间隔内,CPU完成的工作很少,并且它永远不会具有统计意义。

作为参考,Windows时钟的准确度约为10毫秒(早期版本较少)。 通过调用DateTime.UtcNow来包装代码不会比这更好。

在你的问题中,你谈到想要“举办活动”。 问题是,以特定间隔引发事件的唯一类型的计时对象是Timer对象。 它在.NET Framework中有3种不同的版本( System.Timers.TimerSystem.Threading.TimerSystem.Windows.Forms.Timer ),所有这些都有自己独特的使用场景和相对怪癖,但没有一个它们可以保证精确度,满足您的要求 。 它们甚至没有设计成这样做,也没有任何等效的function由Windows API公开,它们将提供这种类型的精度。

之所以我问你为什么要这样做,以及你是否想要进行基准测试,是因为这会改变整个游戏。 .NET Framework(从2.​​0版开始)提供了一个Stopwatch对象 ,该对象专门用于精确测量基准测试或性能分析等情况所用的时间。 Stopwatch简单地包装了Windows API函数QueryPerformanceFrequencyQueryPerformanceCounter (它应该确认我对其预期用途的建议)。 我们以前必须使用P / Invoke这些函数来在早期版本的Framework中访问这种类型的function,但它现在已经方便地内置了。 如果你需要一个具有相对较高分辨率的计时器来进行基准测试,那么Stopwatch是你最好的选择。 从理论上讲,它可以为您提供亚微秒的时序。

但它并非没有问题。 它不会引发任何事件,因此如果您当前的设计依赖于事件处理,那么您将不得不重新考虑它。 并且, 它也不能保证完全准确。 当然,鉴于硬件限制,它可能具有最高的分辨率 ,但这并不意味着它必然符合您的规定要求。 例如,在多处理器系统上可能不可靠,其中必须在同一处理器上执行StartStop 。 它应该没关系,但确实如此 。 它也可能在处理器上不可靠 ,可以上下调节时钟速度。 我甚至敢提到,调用QueryPerformanceCounter本身需要花费一些时间 – 大约5微秒,即使在现代的2+ GHz处理器上也是如此,这使您无法实现理论上听起来很好的亚微秒时序。 然后,任何合理的代码分析器都会认为这个时间量可以忽略不计,因为它确实如此
(另见: http : //www.devsource.com/c/a/Techniques/High-Performance-Timing-under-Windows/2/ )

各种计时器类使用更大的粒度。 Threading.Timer和Timers.Timer都使用1/64秒,即15.625毫秒。

如果你所指的’tick’是100纳秒刻度,由DateTime类,TimeSpan类使用,并由秒表输出,那么你要问的11刻度长度是1,100纳秒,或1.1微秒。 据我所知,没有内置计时器可以为您提供该分辨率。 如果你确实希望事件每1.1微秒发生一次,你将不得不删除“计时器”的想法,而是考虑一个短暂的延迟。 使线程具有高优先级,并在循环中运行您的事件。 不要调用Thread.Sleep(),因为我认为1.1微秒小于系统调度程序的时间片。 你需要做一个延迟循环。

另外,要意识到你所询问的时间间隔非常非常小。 在2 GHz处理器上,1.1微秒仅为2,200个处理器周期。 不是一个微不足道的数量,但没有很多时间来完成大量的工作。 如果你正在谈论你在评论中所说的1个滴答,那只有200个处理器周期:这是足够的时间来做几十个数学运算,也许可以调用一个函数。