C#,System.Timers.Timer,以系统时钟同步每分钟运行

3
我正在尝试让一个计时器每分钟与系统时钟同步运行(00:01:00, 00:02:00, 00:03:00等)。以下代码是否能产生稳定的计时器?我已经尝试运行它。计时器确实每分钟精确运行。但问题是,几个月后它会不会开始偏离时间?
private System.Timers.Timer timer;

public frmMain()
{
            timer = new System.Timers.Timer();
            timer.AutoReset = false;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Interval = GetInterval();
            timer.Start();
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
            //Do processing

            timer.Interval = GetInterval();
            timer.Start();

}
private double GetInterval()
{
            DateTime now = DateTime.Now;
            return ((60 - now.Second) * 1000 - now.Millisecond);
}

4个回答

4

不会。

DateTime.Now 使用系统时钟作为参考定时器,因此您的定时器始终会与其保持同步,除了几毫秒的系统时钟分辨率。


0

我不明白它怎么会偏离,每次计时器滴答作响时,它都会确定到下一个精确分钟还有多长时间,并相应地设置间隔。理论上,这实际上是非常巧妙的,因为单独的计时器会偏离。当然,唯一确定的方法是测试它,只要您的用户界面不冻结超过60秒(也许50秒更保险),就不会有问题。请记住,笔记本电脑经常在一段时间内未使用或盖上盖子后进入睡眠状态,这会导致故障。

根据您尝试做什么,为什么不直接使用系统时间,在每次分钟变化时发送事件呢?


0

你的代码不会漂移,但由于计时器回调很少完全按照请求的间隔时间执行,所以会有抖动。

我唯一能看到的潜在问题是,如果ThreadPool负载过重,导致你的计时器回调未在一分钟内出队并执行,从而导致跳过一分钟。

这似乎有些不太可能,但也不完全超出可能性的范围。


0

总体来看,情况良好,GetInterval将始终返回正值等等。我只看到了一些注意事项:

  1. 如果发生待机/恢复,则可能会在非整点运行一次
  2. 如果timer_Elapsed需要超过一分钟才能完成,则会错过一个节拍
  3. 如果系统过载,导致timer_Elapsed被调度延迟40/50秒,并且timer_Elapsed需要超过60-delay秒,则会错过一个节拍

这取决于你有多重视不错过任何一分钟,你期望计划操作运行的程度(最坏时间),以及你想要实现什么。 - miniBill
1
正如Bill所说,解决方案取决于问题。如果您需要每天运行1440次(即每分钟一次),那么也许您应该跟踪它已运行多少次,以及应该运行多少次。如果它是一个需要每分钟运行的计时器,则在每个节拍时都要检查它是否在上一分钟内运行,如果没有则运行两次此次操作等等... - General Grey
如果它正在轮询更新,那么您可以完全忽略跳过的心跳等等... [顺便说一句,我的真名不是比尔 xD] - miniBill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接