gpt4 book ai didi

c# - 每 24 小时触发一次计时器回调 - DST 是否正确处理?

转载 作者:行者123 更新时间:2023-11-30 16:15:54 25 4
gpt4 key购买 nike

我只是想过我解决每 24 小时运行一次任务的服务的方式,以及 DST 可能如何伤害它。

为了每天运行任务,我使用了一个 24 小时周期的 System.Threading.Timer,如下所示:

_timer = new System.Threading.Timer(TimerCallback, null,
requiredTime - DateTime.Now, new TimeSpan(24, 0, 0));

突然想到夏令时校正我有三个想法:

  • DST 没用,我们应该摆脱它。
  • 计时器是否正确处理了这个问题?我认为不是 - 它只是等待 24 小时 - 无论时钟是否改变。它只是等待指定的时间段,然后再次调用 TimerCallback。
  • DST 毫无用处,我们真的应该摆脱它。

我的第二个想法是否正确?如果是,我该怎么做才能避免这个问题?如果发生 DST 更正,任务不得晚于或早于一小时运行。

最佳答案

SystemEvents.TimeChanged 会告诉您时钟是否已被用户更改。它不会随着时钟的每个滴答声定期触发。所以它对安排事件没有用,除了你可能会在它发生时重新计算计时器。 (我认为如果系统与时间服务器同步,它也会触发,但我对此并不乐观。)

如果您尝试按照 Hans 的建议计算墙上时间的差异,请小心。您不能只使用 DateTime。观察:

// With time zone set for US Pacific time, there should only be 23 hours
// between these two points
DateTime a = new DateTime(2013, 03, 10, 0, 0, 0, DateTimeKind.Local);
DateTime b = new DateTime(2013, 03, 11, 0, 0, 0, DateTimeKind.Local);
TimeSpan t = b - a;
Debug.WriteLine(t.TotalHours); // 24

即使指定了本地种类,它也不会考虑 DST。

如果您打算采用这种方法,则必须使用 DateTimeOffset 类型。

DateTimeOffset a = new DateTimeOffset(2013, 03, 10, 0, 0, 0, TimeSpan.FromHours(-8));
DateTimeOffset b = new DateTimeOffset(2013, 03, 11, 0, 0, 0, TimeSpan.FromHours(-7));
TimeSpan t = b - a;
Debug.WriteLine(t.TotalHours); // 23

您可能需要通过以下方式收集您的输入:

DateTime today = DateTime.Today;      // today at midnight
DateTime tomorrow = today.AddDays(1); // tomorrow at midnight

TimeZoneInfo tz = TimeZoneInfo.Local;
DateTimeOffset a = new DateTimeOffset(today, tz.GetUtcOffset(today));
DateTimeOffset b = new DateTimeOffset(tomorrow, tz.GetUtcOffset(tomorrow));

TimeSpan t = b - a;
Debug.WriteLine(t.TotalHours); // 23, 24, or 25 depending on DST

但是 - 将单个计时器设置为运行这么长时间可能不是一个好主意。不仅时钟可能会被用户更改或系统时间同步,而且应用程序或系统可能会关闭或重新启动。此外,如果您有许多这样的任务,您最终可能会因为闲置而消耗大量资源。

一个想法是保留下一次触发事件的列表。在您的应用程序中,您将触发一个短暂的轮询计时器(比如每分钟一次左右),并将当前时间与列表中的值进行比较,以了解您是否真的需要做任何事情。

另一个想法是它的轻微变化。您可以对列表进行排序,而不是进行短轮询,并设置一个延迟时间,直到下一个事件,最大延迟时间(可能是一个小时)。同样,当计时器触发时,您会看到是否有任何事情要做,或者是否需要设置另一个计时器延迟。您必须在应用程序启动时以及安排新事件时运行它。

对于这些方法中的任何一种,您都应该使用 DateTimeOffset 或等效的 UTC DateTime 进行安排。否则,您可能会在 DST 的错误时间触发 - 甚至在 DST 回退过渡期间触发两次

如果所有这些听起来太复杂,那么您可以尝试使用预构建的解决方案,例如 Quartz.net .特别是阅读 this section of their FAQ .

关于您的第一个和第三个要点,我完全同意 - 但它永远不会发生。即使它确实发生了,我们仍然必须考虑它确实发生的所有多年历史。如果你还没有看过 this video已经,你应该。

关于c# - 每 24 小时触发一次计时器回调 - DST 是否正确处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19046211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com