gpt4 book ai didi

.net - System.Timer elapsed 事件似乎在 .Net 中以较短的时间间隔延迟触发

转载 作者:行者123 更新时间:2023-12-04 14:42:40 26 4
gpt4 key购买 nike

我正在通过 UART 端口对系统进行采样,然后将信息记录到带有时间戳(包括毫秒)的文件中。如果我以 1 秒的间隔进行采样,数据会按预期返回……类似于

1:52:45 PM 750 data
1:52:45 PM 750 data
1:52:45 PM 750 data
1:52:46 PM 750 data

但是,如果我将计时器的间隔减少到 100 毫秒,数据就会返回

1:52:45 PM 531 data
1:52:45 PM 640 data
1:52:45 PM 750 data
1:52:45 PM 859 data
1:52:45 PM 968 data
1:52:46 PM 78 data

总是迟到一点。

定时器间隔越小情况越糟...我在这里错过了什么?

最佳答案

时钟漂移。非常典型的普通计时器。这样做的原因是它们通常是使用 sleep 功能实现的。 sleep 函数总是保证至少在指定的时间内 sleep ,但不保证不会 sleep 超过指定的时间,实际上它总是在累积漂移。

有一些方法可以编写补偿漂移并平均命中目标的计时器。

我最喜欢的计时器之一是固定步进计时器,它有一个谨慎的滴答声。它非常简单,看起来像这样:

var t = DateTime.Now + TimeSpan.FromSeconds(1);
for (;;)
{
if (DateTime.Now >= t)
{
t += TimeSpan.FromSeconds(1); // Tick!
}
}

这是一个粗糙但有效的计时器,下面这个是我为 WPF 计时器构建的时钟示例,其中内置计时器存在漂移问题。这个定时器要复杂得多,它不会占用你的 CPU。但它清楚地说明了定时器的典型问题。

这里的 OnTimerTick 使用的是一个内置定时器,它会发生漂移,但它会调整间隔以补偿漂移。

/// <summary>
/// Occurs when the timer interval has elapsed.
/// </summary>
public event EventHandler Tick;

DispatcherTimer timer;

public bool IsRunning { get { return timer.IsEnabled; } }

long step, nextTick, n;

public TimeSpan Elapsed { get { return new TimeSpan(n * step); } }

public FixedStepDispatcherTimer(TimeSpan interval)
{
if (interval < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("interval");
}
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(OnTimerTick);
this.step = interval.Ticks;
}

TimeSpan GetTimerInterval()
{
var interval = nextTick - DateTime.Now.Ticks;
if (interval > 0)
{
return new TimeSpan(interval);
}
return TimeSpan.Zero; // yield
}

void OnTimerTick(object sender, EventArgs e)
{
if (DateTime.Now.Ticks >= nextTick)
{
n++;
if (Tick != null)
{
Tick(this, EventArgs.Empty);
}
nextTick += step;
}
var interval = GetTimerInterval();
Trace.WriteLine(interval);
timer.Interval = interval;
}

public void Reset()
{
n = 0;
nextTick = DateTime.Now.Ticks;
}

public void Start()
{
var now = DateTime.Now.Ticks;
nextTick = now + (step - (nextTick % step));
timer.Interval = GetTimerInterval();
timer.Start();
}

public void Stop()
{
timer.Stop();
nextTick = DateTime.Now.Ticks % step;
}

关于.net - System.Timer elapsed 事件似乎在 .Net 中以较短的时间间隔延迟触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5265259/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com