毫秒等待的C#定时器

每隔n * x毫秒我执行一次动作,其中n = 0,1,2,…; x是一些增量。

示例 – 每25毫秒执行一次计算。

对于每个增量,此操作可能需要不到x秒。 因此,我需要在C#中使用一种方法来等待剩余的(x – actual_time)毫秒。

示例 – 如果计算只需要20毫秒,我需要再等待5个毫秒才能重新运行计算。

请指教。

谢谢,凯文

我需要在C#中使用一种方法来等待剩余的(x – actual_time)毫秒。

我认为这是在Windows上运行的C#。

还有你的问题。 Windows不是“实时”操作系统。

如果您需要毫秒级别的计时精度,那么您可以做的最好的事情是将线程的线程优先级设置得非常高,然后在查询高性能计时器(秒表)时忙等待。

你不能屈服于另一个线程 ; 另一个线程可以在操作系统上下文切换之前运行多达16毫秒,当然除非你是最高优先级的线程,否则你无法保证在16毫秒之后控制权回到你身上。

现在,将线程优先级设置为高然后忙碌等待是您可能做的最粗鲁的事情之一; 基本上你将控制用户的机器,不允许他们用它做任何其他事情。

因此,我要做的就是完全放弃这一行动 。 或者,(1)考虑获得专为实时过程控制而设计的操作系统(如果实际上是您的应用程序),而不是为多任务业务应用程序设计的多任务操作系统。 或者(2)放弃要求动作恰好每25毫秒发生一次。 只需执行一次计算,然后将量子的剩余部分输出到另一个线程。 当你获得控制权时,看看你屈服后是否超过25毫秒; 如果没有,再次屈服。 如果有,请重新开始并执行计算。

在像Windows这样的非实时操作系统中,很难达到这种准确度。 你最好的选择可能是调查多媒体计时器。

其他.NET计时器将不具备您需要的那种解决方案。

在25ms时,您可能是.Net中可用计时器分辨率的错误一面。

然而 – 作为一般解决方案,我可能会以不同的方式尝试这种“做计算……等到25ms已经过去”的方法。

更好的方法可能是在25ms触发器上使用System.Timers.Timer来触发计算。

var timer = new Timer(25); timer.Elapsed += (sender, eventArgs) => { DoCalc(); }; timer.Start(); 

在上面的示例中,将每25 ms调用一次DoCalc方法(尽管有计时器分辨率问题)。 如果您的计算超出了规定的时间,您需要考虑该怎么做。 按照目前的情况,上面的代码将允许第二次计算开始,即使之前的计算尚未完成。

这是一个困难的选择,你的选择相当有限,正如Eric Lippert和Matt Burland指出的那样。 基本上,你也可以

  • 使用多媒体计时器(谷歌“多媒体计时器组件”或“winmm.dll”),虽然从Windows Vista不再推荐支持时间分辨率低至0.500毫秒,但需要Win32互操作,可能会提高你的CPU使用率非常明显,或
  • 得出一个近似的时间切片算法,该算法将使用标准计时器(在多核桌面上的分辨率通常为15.625毫秒),根据自上次计时器滴答后经过的所需和实际时间的差异,动态改变每个滴答的计时器间隔(您可以使用高分辨率CPU性能计数器(例如秒表类)相当准确地测量它。

后一种解决方案在统计上会为您提供样品使用情况下的40Hz定时器,但由于您使用的定时器分辨率较低,您将产生明显的抖动。

这是权衡,这是你的要求。

这是我写的高精度计时器。 我以25ms的间隔获得大约<1ms的平均精度。 但如果Windows很忙,可能会迟到。 它相当依赖CPU利用率。 随意使用。 它使用Sleep(1),当下一个tick超过15ms时,然后SpinUntil(根据需要产生)以保持CPU使用率。 使用.NET4功能。

链接: 高精度定时器