我有一个始终运行的服务,它有一个定时器,每天凌晨2点执行一个特定的操作。System.Threading.Timer调用每天漂移几秒钟
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
,首先启动该服务时,初始化代码被调用一次,在过去的几天里,当计时器已经解雇我已经登录:
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点)。
我使用它是错的还是这个计时器没有被设计为准确?我可以每天重新创建计时器,或者在一小段时间内重新启动计时器,然后重复检查是否要执行该操作,但这看起来有点不方便。
编辑
我尝试使用System.Timers.Timer,它似乎有同样的问题。在正在重置的间隔是因为你不能在System.Timers.Timer第一前打勾安排的初始时间就像你可以在System.Threading.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
功能需要2秒吗? – rerun 2011-06-06 23:24:27
计时器刚刚启动事件,是否真的要等待工作线程在重新计划事件之前完成?我不知道该功能需要多久才能完全是,它可以在2秒左右 – BrandonAGr 2011-06-07 00:09:06
那岂不是更好地使用计划任务窗口。 – rerun 2011-06-07 00:21:45