毫秒等待的C#定时器

时间:2012-03-27 14:47:13

标签: c# timer

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

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

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

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

请告知。

谢谢, 凯文

5 个答案:

答案 0 :(得分:13)

  

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

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

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

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

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

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

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

答案 1 :(得分:4)

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

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

答案 2 :(得分:1)

在25毫秒时,您可能是.Net中可用计时器解决方案的错误一面。

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

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

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

在上面的示例中,将每25 ms调用一个DoCalc方法(尽管有计时器分辨率问题)。如果计算 overran ,则需要考虑如何处理。按照目前的情况,上面的代码将允许第二次计算开始,即使之前的计算尚未完成。

答案 3 :(得分:1)

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

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

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

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

答案 4 :(得分:1)

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

链接:High Precision Timer