0

我有一些从表格中读取HH:MM:SS的计时器,以确定每天何时运行。

例如:
定时器 A 需要每周一 13:00:00 运行
定时器 B 需要每周二 02:00:00 运行
定时器 C 需要每小时运行一次

因此,在我的代码中,我计算出当前时间是多少,然后计算从DateTime.Now()计时器应该运行的下一次出现的毫秒数。当计时器的Elapsed事件完成后,它会重新计算下一次应该运行的时间。由于时间变化,这在本周末造成了一个问题。

有一个更好的方法吗?会DateTime.UtcNow是更好的选择吗?也许将数据库中的时间字符串转换为 UTC 时间,然后找出DateTime.UtcNow()而不是之间的区别DateTime.Now()

4

1 回答 1

-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 值相当小且为正值,则您可以休眠直到运行时间。如果它变得小而消极,你睡过头了——立即跑(睡过头常见)。

将天数添加到当前的午夜值,然后将时间添加到该值,然后计算等待多长时间,即使在转换日也是一种获得合理运行时间的方法。

于 2015-11-03T13:50:46.523 回答