定时器比间隔多花 10 毫秒

发布于 2024-09-04 08:04:44 字数 905 浏览 2 评论 0原文

我使用的是间隔 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}

I am using a timer with interval 1 second.
But in the timer's tick event when I print the time it's always 62 or 65 ms.
I don't understand why it's taking 10 ms more.

Please can some one have look into this.

Here is the code I am using:

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();
}

And this the output:

{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}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

天涯沦落人 2024-09-11 08:04:44

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

当涉及到较小的间隔时,我将 Windows 计时器描述为“尽力而为”。当间隔足够长时,您不会注意到您没有获得所需的确切间隔。当您越来越接近计时器的分辨率(计时器运行的频率)时,您开始看到开销占间隔增加的百分比。实时系统特别注意最大限度地减少软件开销,依靠更复杂和更快的硬件解决方案。 Windows 计时器的确切频率取决于底层硬件提供的计时服务,因此可能因系统而异。

如果您有实时需求——并且每 50 毫秒执行一次操作可能属于该类别——那么您可能需要考虑专用硬件和/或实时操作系统。

You need to understand that Windows is not a real-time operating system. Real-time operating systems have timer mechanisms that allow the system to make hard guarantees about when timer-initiated events occur and the overhead associated with them, and allow you to specify what behavior should occur when the deadline is missed -- for example if the previous execution took longer than the interval.

I would characterize the Windows timers as "best effort" when it comes to smaller intervals. When the interval is sufficiently long you don't notice that you aren't getting the exact interval that you requested. As you get closer and closer to the resolution of the timer (the frequency at which the timer runs), you start seeing the overhead as a percentage of the interval increase. Real-time systems take special care to minimize the software overhead, relying on more sophisticated and faster hardware solutions. The exact frequency of the Windows timer depends on the timing services that the underlying hardware provides and so may differ from system to system.

If you have real-time needs -- and doing something every 50ms may fall into that category -- then you may need to look at specialized hardware and/or a real-time OS.

相思碎 2024-09-11 08:04:44

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

It's because of the limited resolution of the system clock. The event occurs at the next system tick after the specififed time, so you will always get a few extra milliseconds.

半衬遮猫 2024-09-11 08:04:44

如果你需要更精确的定时器,你可以挂接Win32多媒体定时器,它是最精确的定时器(低至1ms)。这是关于 CodeProject 的文章,展示了如何从 C# 连接到它。

If you need a more precise timer, you can hook into the Win32 Multimedia Timer, it is the most accurate timer (down to 1ms). Here's an article on CodeProject showing how to hook into it from C#.

可是我不能没有你 2024-09-11 08:04:44

首先,正如其他人所指出的,您将其设置为 1 秒,而不是 50 毫秒。

其次,Windows不是实时操作系统。没有一个计时器类是完全精确的。你所做的一切都表明你想至少等这么久。一切都需要一段时间才能触发,一旦窗口开始实际处理滴答消息,您最终会收到计时器已滴答的通知。

First, as other people have noted, you're setting it to 1s, not 50ms.

Secondly, windows is not a real-time OS. None of the timer classes are exactly precise. All you're doing it saying that you want to wait at least this long. It takes some amount of time for everything to fire and you to end up notified that the timer has ticked once windows gets around to actually servicing the tick message.

居里长安 2024-09-11 08:04:44

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

Note that usually, in most language, sleep calls specify the minimum time after which a process would awaken. After the specified time has passed, the process is put on a queue and hopefully the scheduler activates it. But this activation may sometimes be delayed. I'm not sure about the Timer class, but I suspect it may suffer from a similar problem.
You may perhaps try to increase the priority of your process to cut down the increased time.

新雨望断虹 2024-09-11 08:04:44

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

另外,为了在示例中获得更好的准确性,请更改时间测量代码以使用 Stopwatch 类。

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();
        }

System.Timers.Timer is not a precise timer. Especially when system is under load it can have even bigger delays.

Also to get better accuracy in your example change time measuring code to use Stopwatch class.

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();
        }
俏︾媚 2024-09-11 08:04:44

使用系统计时器总是比请求的值长一点。这是由于系统中其他进程的开销造成的。

Using the system timers will always be a little longer than the value requested. This is due to the overhead of the other processes in the system.

悟红尘 2024-09-11 08:04:44

在我的系统上是 14 毫秒。谷歌搜索后;差异在于上下文线程切换延迟。 这里有一篇关于高分辨率计时器的文章

On my system it's 14ms. Having googled; the difference is down to context thread switching delay. There's an article regarding high resolution timers here

猫卆 2024-09-11 08:04:44

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

-S!

As other responders have mentioned, Windows is not a real-time OS. If you must use windows, try using Win CE or Windows Embedded.

-S!

我不吻晚风 2024-09-11 08:04:44

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

The accuracy of the time may depend on how many processes run. If you have that option , I would reduce the number of processes that run on your computer one by one and I mean those which consume significant cpu time,I would check if the times improve. Especially, browsers, virus scanners,programs running in the background.

萧瑟寒风 2024-09-11 08:04:44

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

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;

这些是代码片段。您可以尝试使用它们来查看控制台中的值。

The deviations are normal since they are not RTOS (real time operating systems). This is the best solution that I've found under the circumstances: 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;

Those are the code snippets. You can try them to see the values in the console.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文