2010-06-07 62 views
3

我使用间隔为1秒的定时器。 但是在计时器的滴答事件中,当我打印时间时,它总是62或65毫秒。 我不明白为什么它需要10毫秒以上。定时器比间隔多花10ms

请有人可以看看这个。

这里是我使用的代码:

static int _counter; 
var _timer = new System.Timers.Timer(1000); 
public Form1() 
{ 
    InitializeComponent();   
    _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); 
    _timer.Start();    
} 

private void _timer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    Console.WriteLine(DateTime.Now.ToString("{hh:mm:ss.fff}"));   
    _counter++; 
    if (_counter == 20) 
     _timer.Stop(); 
} 

而这种输出:

{01:59:08.381} 
{01:59:09.393} 
{01:59:10.407} 
{01:59:11.421} 
{01:59:12.435} 
{01:59:13.449} 
{01:59:14.463} 
{01:59:15.477} 
{01:59:16.491} 
{01:59:17.505} 
{01:59:18.519} 
{01:59:19.533} 
{01:59:20.547} 
{01:59:21.561} 
{01:59:22.575} 
{01:59:23.589} 
{01:59:24.603} 
{01:59:25.615} 
{01:59:26.629} 
{01:59:27.643} 
+1

您的问题描述和示例不一致。该示例的设置间隔为1秒,似乎显示间隔为1秒,而不是50毫秒 – simon 2010-06-07 12:25:29

回答

15

您需要了解Windows不是实时操作系统。实时操作系统具有定时器机制,可以使系统对定时器启动事件何时发生及其相关开销做出硬性保证,并允许您指定错过最后期限时发生的行为 - 例如,如果先前的执行时间比间隔长。

当谈到更小的间隔时,我会将Windows定时器描述为“尽力而为”。当间隔足够长时,您不会注意到您没有得到您请求的确切时间间隔。随着您越来越接近计时器的分辨率(计时器运行的频率),您开始将开销视为间隔增加的百分比。实时系统需要特别小心,以最小化软件开销,依靠更复杂,更快速的硬件解决方案。Windows定时器的确切频率取决于底层硬件提供的定时服务,因此可能因系统而异。

如果您有实时需求 - 并且每50ms执行一次可能会属于该类别 - 那么您可能需要查看专用硬件和/或实时操作系统。

2

需要注意的是,通常,在大多数语言,睡眠调用指定的最小时间之后,进程将唤醒。经过指定的时间后,该进程将放入队列中,并希望调度程序激活它。但是这种激活有时可能会延迟。我不确定Timer类,但我怀疑它可能遭受类似的问题。
您可能会尝试增加流程的优先级以缩短增加的时间。

1

使用系统定时器将总是比请求的值稍长。这是由于系统中其他进程的开销。

6

这是因为系统时钟的分辨率有限。该事件发生在指定时间后的下一个系统时钟周期中,因此您将总能获得几毫秒的额外毫秒数。

1

System.Timers.Timer不是一个精确的计时器。特别是当系统处于负载下时,它可能会有更大的延迟。

此外,为了在示例更改时间测量代码中使用秒表类获得更好的准确性。

static int _counter; 
     System.Timers.Timer _timer = new System.Timers.Timer(1000); 
     Stopwatch sw; 
     public Form1() 
     { 
      InitializeComponent();   
      _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); 
      _timer.Start();    
      sw = Stopwatch.StartNew(); 
     } 

     void _timer_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      Console.WriteLine(sw.ElapsedMilliseconds);   
      _counter++; 
      if (_counter == 20) 
       _timer.Stop();    

      sw.Reset(); 
      sw.Start(); 
     } 
4

首先,正如其他人所指出的,您将其设置为1秒,而不是50毫秒。其次,windows不是实时操作系统。没有一个定时器类是精确的。你所做的只是说你要等这么长时间至少。需要一定的时间才能触发所有事件,并且一旦窗口实际服务于滴答信息,您最终会通知计时器已经打勾。

+0

通过在绑定到单个CPU内核的线程中使用性能计数器来校准高分辨率计时器,可以使Windows的性能更好。我认为。我已经看到它完成了,但没有写出有关代码,需要一些非常低级的技术(即可能是直接的机器代码!),并且在这个领域存在恶意的固件错误。几乎不用担心时钟精度IMO ... – 2010-06-07 12:50:43

+0

在处理A/D外围设备,传感设备和医疗设备时,定时精度非常重要。这是非常非常重要的。 但是,正如@Donnie指出的那样,Windows不是实时操作系统。如果您必须*使用Windows操作系统,请尝试WinCE或Windows Embedded。 – 2010-06-07 13:13:22

3

如果您需要更精确的定时器,您可以挂接到Win32多媒体定时器,它是最准确的定时器(最低1ms)。这里有一篇关于CodeProject的文章,展示了如何从C#中挂钩它。

1

在我的系统上它是14ms。通过Google搜索;区别在于上下文线程切换延迟。有一篇关于高分辨率定时器的文章here

1

正如其他响应者所说,Windows不是实时操作系统。如果您必须使用Windows,请尝试使用Win CE或Windows Embedded。

-S!

1

时间的准确性可能取决于运行的进程数。如果你有这个选择,我会减少在你的计算机上运行的进程的数量,我的意思是那些消耗大量CPU时间的进程,我会检查时间是否改善。尤其是浏览器,病毒扫描程序,在后台运行的程序。