System.Timer经过的事件似乎火迟到短的时间间隔在.net [英] System.Timer elapsed event seems to fire late for short intervals in .Net
问题描述
我取样系统通过UART端口,然后记录在一个文件中的信息与时间戳(包括毫秒)。如果我品尝每隔1秒,数据回来预期...类似
I am sampling a system over the UART port, and then logging the info in a file with a timestamp (including milliseconds). If I sample at 1 second intervals, the data comes back as expected...something like
下午1时52分45秒750的数据 下午1时52分45秒750的数据 下午1时52分45秒750的数据 下午1时52分46秒750的数据
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毫秒的间隔中,将数据回来
However, if I decrease the interval of the timer to 100 ms, the data comes back
下午1时52分45秒531的数据 下午1时52分45秒640的数据 下午1时52分45秒750的数据 下午1时52分45秒859的数据 下午1时52分45秒968的数据 下午1时52分46秒78的数据。
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
总是有点晚了。
更糟糕较小的计时器时间间隔......我缺少什么吗?
It gets worse with smaller timer intervals...what am I missing here?
推荐答案
时钟漂移。非常典型的琐碎的定时器。这样做的原因是,它们通常使用的是睡眠功能实现。睡眠功能,始终保证睡眠至少指定的时间,但不能保证不睡觉比更多的时间,在实践中,总是积累了漂移。
Clock drift. Very typical for trivial timers. The reason for this is that they are typically implemented using a sleep function. A sleep function is always guaranteed to sleep for at least the time specified but not guaranteed to not sleep for more time than that, in practice it's always accumulating a drift.
有办法写定时器,补偿漂移,平均命中目标。
There are ways to write timer that compensate for the drift and on average hit the target.
我最喜欢的定时器定步的人,有一个不显眼的刻度。这很简单,看起来是这样的:
One of my favorite timers are fixed step ones, that have a discreet tick. It's very simple and looks like this:
var t = DateTime.Now + TimeSpan.FromSeconds(1);
for (;;)
{
if (DateTime.Now >= t)
{
t += TimeSpan.FromSeconds(1); // Tick!
}
}
这是一个粗糙但有效的定时器,这下一个是时钟我建立了一个WPF计时器,其中内置的定时器漂流遭受的例子。该定时器是一个复杂得多,它不养猪你的CPU。但clearily表明定时器具有典型的问题。
That's a crude but effective timer, this following one is an example of a clock I built for a WPF timer where the built in timer was suffering from drifting. This timer is a lot more complex and it does not hog your CPU. But it clearily illustrates typical issues that timers have.
这里使用的是内置计时器遭受漂移,但它调整的时间间隔,以补偿漂移的OnTimerTick
The OnTimerTick here is using a built in timer that suffers from drift but it's adjusting the interval to compensate for the drift.
/// <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;
}
这篇关于System.Timer经过的事件似乎火迟到短的时间间隔在.net的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!