定时器比间隔多10 ms

时间:2010-06-07 12:18:16

标签: c# .net timer

我正在使用间隔为1秒的计时器。 但是在计时器的刻度事件中,当我打印时间时,它总是62或65毫秒。 我不明白为什么它要多花10毫秒。

请有人调查一下。

以下是我正在使用的代码:

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}

11 个答案:

答案 0 :(得分:15)

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

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

如果您有实时需求 - 并且每50毫秒做一些事情可能属于该类别 - 那么您可能需要查看专用硬件和/或实时操作系统。

答案 1 :(得分:6)

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

答案 2 :(得分:4)

首先,正如其他人所说,你将它设置为1秒,而不是50毫秒。

其次,Windows不是实时操作系统。没有一个计时器类是完全精确的。所有你这样做,说你要等至少这么久。所有东西都需要花费一些时间才能触发,并且一旦窗口到达以实际处理刻度消息,您最终会通知计时器已经勾选。

答案 3 :(得分:4)

如果你需要一个更精确的计时器,你可以挂钩到Win32多媒体计时器,它是最准确的计时器(低至1毫秒)。这是一篇关于CodeProject的文章,展示了如何从C#中加入它。

答案 4 :(得分:2)

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

答案 5 :(得分: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();
        }

答案 7 :(得分:1)

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

答案 8 :(得分:1)

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

-S!

答案 9 :(得分:1)

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

答案 10 :(得分:0)

偏差是正常的,因为它们不是 RTOS (实时操作系统)。这是我在这种情况下找到的最佳解决方案:Link

Program.MicroTimer microTimer = new Program.MicroTimer();
microTimer.MicroTimerElapsed += new Program.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEvent);
microTimer.Interval = 1000; // Call micro timer every 1000µs (1ms)

// Can choose to ignore event if late by Xµs (by default will try to catch up)
// microTimer.IgnoreEventIfLateBy = 500; // 500µs (0.5ms)

microTimer.Enabled = true; // Start timer
System.Threading.Thread.Sleep(2000);
microTimer.Enabled = false;

这些是代码片段。您可以尝试在控制台中查看值。