我有一些计时器从表中读取HH:MM:SS
以确定何时每天运行。
例如:
定时器A需要每周一13:00:00运行
计时器B需要每周二02:00:00运行
定时器C需要每小时运行
所以在我的代码中,我弄清楚当前时间是多少,然后计算从DateTime.Now()
到计时器应该运行的下一次出现的毫秒数。当计时器的Elapsed
事件完成后,它会重新计算它应该在下一次运行的时间。由于时间的变化,这在本周末造成了问题。
有更好的方法吗? DateTime.UtcNow
会更好吗?也许将数据库中的时间字符串转换为UTC时间,然后找出DateTime.UtcNow()
而不是DateTime.Now()
之间的差异?
答案 0 :(得分:-1)
你可以做几件事来解决这个问题。
一种是将UTC用于所有预定作业。这为您提供了一个强大且可预测的系统,没有很多复杂性或测试负担。但是,夏季周一03:00的工作将在冬季的02:00运行。如果可以,那么UTC策略是好的。
(测试时区切换用例很痛苦,如果你使用UTC来减少测试负担,那么。
另一个是认真对待你的日期算术,并且要非常小心。即使在转换日期,C#的DateTime类也可以很好地完成日期算术。
所以,让我们说你需要在周日的01:30每周进行一次流程。那是在美国的噩梦中......它在春季转换中并没有发生,并且在秋季转换中发生了两次。但是你仍然希望这个过程运行一次。
你做的是:保持"下一个预定的时间"值。每次完成作业后,计算"下一个预定时间"下一次运行的价值。这可能是这样的:
var today = DateTime.Today.AddDays(7); /* midnight a week from now */
TimeSpan runTime = TimeSpan.Parse("01:30");
var nextRun = today + runTime;
然后,保存nextRun DateTime值。稍后您可以确定下一次运行之前的时间。这是一个很好的方法。还有其他人。
var msUntilNextRun = (nextRun.Ticks - DateTime.Now.Ticks) / 10000;
如果msUntilNextRun值合理地小而且积极,那么您可以睡觉直到它运行的时间。如果它出现小而负,你睡过头 - 立即跑(睡过头非常常见)。
将天数添加到当前的午夜值,然后将时间添加到该值,然后计算等待的时间,即使在转换日也能获得合理的运行时间。