我有一个始终运行的服务,它有一个计时器,每天凌晨 2 点执行特定操作。
TimeSpan runTime = new TimeSpan(2, 0, 0); // 2 AM
TimeSpan timeToFirstRun = runTime - DateTime.Now.TimeOfDay;
if (timeToFirstRun.TotalHours < 0)
{
timeToFirstRun += TimeSpan.FromDays(1.0);
}
_dailyNodalRunTimer = new Timer(
RunNodalDailyBatch,
null,
timeToFirstRun,
TimeSpan.FromDays(1.0)); //repeat event daily
当服务第一次启动时,初始化代码被调用一次,在过去的几天里,我记录了 Timer 触发的时间:
2011-05-21 02:00:01.580
2011-05-22 02:00:03.840
...
2011-05-31 02:00:25.227
2011-06-01 02:00:27.423
2011-06-02 02:00:29.847
如您所见,它每天漂移 2 秒,离它应该发射的时间(凌晨 2 点)越来越远。
是我用错了还是这个 Timer 的设计不准确?我可以每天重新创建计时器,或者让它每隔一段时间触发一次,然后反复检查我是否要执行该操作,但这似乎有点老套。
编辑
我尝试使用 System.Timers.Timer,它似乎有同样的问题。重置间隔是因为您无法像在 System.Threading.Timer 中那样在 System.Timers.Timer 中的第一个刻度之前安排初始时间
int secondsInterval = 5;
double secondsUntilRunFirstRun = secondsInterval - (DateTime.Now.TimeOfDay.TotalSeconds % secondsInterval);
var timer = new System.Timers.Timer(secondsUntilRunFirstRun * 1000.0);
timer.AutoReset = true;
timer.Elapsed += (sender, e) =>
{
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff"));
if (timer.Interval != (secondsInterval * 1000.0))
timer.Interval = secondsInterval * 1000.0;
};
timer.Start();
产生以下时间,你可以看到它们是如何轻微漂移的:
06:47:40.020
06:47:45.035
06:47:50.051
...
06:49:40.215
06:49:45.223
06:49:50.232
所以我想最好的方法真的是在滴答处理程序中重新安排计时器?以下代码在约 15 毫秒内以固定间隔产生滴答声
double secondsUntilRunFirstRun = secondsInterval - (DateTime.Now.TimeOfDay.TotalSeconds % secondsInterval);
var timer = new System.Timers.Timer(secondsUntilRunFirstRun * 1000.0);
timer.AutoReset = false;
timer.Elapsed += (sender, e) =>
{
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff"));
timer.Interval = (secondsInterval - (DateTime.Now.TimeOfDay.TotalSeconds % secondsInterval)) * 1000.0;
};
timer.Start();
06:51:45.009
06:51:50.001
...
06:52:50.011
06:52:55.013
06:53:00.001
最佳答案
不要让计时器的误差累积。使用 RTC 计算超时时间之前剩余的毫秒数。这次将 Sleep/setInterval 减半。当计时器触发/ sleep 返回时,再次使用 RTC 重新计算剩余的间隔并将间隔/ sleep 再次设置为半衰期。重复此循环,直到剩余间隔小于 50ms。然后 CPU 在 RTC 上循环,直到超过所需时间。触发事件。
Rgds, 马丁
关于c# - System.Threading.Timer 调用每天漂移几秒钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6259120/