System.Timers.Timer的经过时间不正确

时间:2011-09-07 14:21:48

标签: c# .net timer

  

可能重复:
  System.Timer elapsed event seems to fire late for short intervals in .Net

我在Windows服务中使用System.Timers.Timer。间隔设置为60000毫秒,但每隔一段时间,定时器间隔在某些ms上增加。这是日志的例子:

2011-09-05 00:00:37,177 [80] INFO - 
timer_Elapsed;

2011-09-05 00:01:37,187 [8] INFO  - 
timer_Elapsed;

2011-09-05 01:24:38,279 [71] INFO   - 
timer_Elapsed;

但是我需要在37秒内完成计时器,例如,但是在工作一段时间后,我们在38,39,40 ......秒内经过了计时器。

我不需要非常精确的计时器,但我每次需要经过37 + - 1秒..

我如何解决这个问题???


我有一次在Interval属性中设置:

protected override void OnStart(string[] args)
{
   log4net.Config.XmlConfigurator.Configure();
   EmailReminderService.Logger.Info("Service started");

   _timer.Interval =Convert.ToInt32(ConfigurationManager.AppSettings["Interval"]);
   _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
   _timer.Enabled = true;               
}

private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
   EmailReminderService.Logger.Info("timer_Elapsed;");
   EmailReminderManager manager = new EmailReminderManager();
   manager.EmailReminderProcessing();
}

在timer elapsed方法中,不要使用_timer对象..

2 个答案:

答案 0 :(得分:0)

  

我们在38,39,40 ......秒中经过了计时器。

您确定没有使用计时器的Interval属性做某事吗?它可能会有所不同,因为您没有使用Real-time OS,但每次通话时添加的第二个听起来更像是您身边的错误而不是Timer

答案 1 :(得分:0)

在每次迭代中计算现在与您想要触发下一个计时器的时间点之间的时差。然后将间隔设置为该值。这样可以避免漂移。

//Once
DateTime start=DateTime.UtcNow;// Or if you prefer that the event
                               // happens on the same second no matter when
                               // the program started you can simply
                               // use a constant here

//At the end of the timer handler
int interval=(int)((DateTime.UtcNow-start).TotalSeconds*1000);
const int targetInterval=60000;
interval(interval+targetInterval/2)%targetInterval+targetInterval/2;
timer.Interval=interval;

这会选择30到90秒之间的间隔,以便您准确地达到目标时间。

该程序与UtcNow<start优雅地交易,因为当用户更改系统时钟时可能会发生这种情况。