如何让 DispatcherTimer 设置一个超过 24 天的计时器?

How can I get DispatcherTimer to set a timer longer than 24 days?

我的代码使用 System.Windows.Threading.DispatcherTimer 设置计时器。

有一天我发现自己试图设置一个比平时更大的计时器,结果我得到了一个 ArgumentOutOfRangeException:

System.ArgumentOutOfRangeException: TimeSpan period must be less than or equal to Int32.MaxValue.

然而,即使在 .NET TimeSpans 使用的 100ns 单位 ("ticks") 中,我的值(大约 41 天和 15½ 小时,或 3,598,196,944 毫秒,或 3.5981969e+13 个滴答— 诚然,很多刻度)应该在 64 位整数的 运行ge 范围内,这是文档声称 TimeSpan 在内部使用的内容(并且由 TimeSpan 构造函数采用刻度)。

由于Int32.MaxValue为2,147,483,647,建议DispatcherTimer最多只支持将近25天的时长。但是 DispatcherTimer 文档没有提到这个限制。

我运行一些测试,确实:

#include <cstdint>

using namespace System;
using namespace System::Windows;
using namespace System::Windows::Threading;

void tick(System::Object^ sender, System::EventArgs^ args) {}

int main()
{
    // Duration is in 100ns units (10m per second).
    const TimeSpan delay1(2147483647ULL * 10000);

    const TimeSpan delay2(2147483648ULL * 10000);

    // Fine
    DispatcherTimer^ timer1 = gcnew DispatcherTimer(
        delay1,
        DispatcherPriority::Normal,
        gcnew EventHandler(&tick),
        Dispatcher::CurrentDispatcher
    );

    // System.ArgumentOutOfRangeException
    DispatcherTimer^ timer2 = gcnew DispatcherTimer(
        delay2,
        DispatcherPriority::Normal,
        gcnew EventHandler(&tick),
        Dispatcher::CurrentDispatcher
    );
}

我的意思是,好吧,我可以通过按顺序设置更短的延迟(比如一次最多一天)来解决这个问题,但我想尽可能避免这种复杂性。

我的观察准确吗?如果是这样,有什么办法可以改变这种未记录的行为吗?

[Windows 10 (v1803),Visual Studio 2019 (v16.4.5),.NET 4.7.03056,x64 build]

当文档失败时,让我们看一下旧的源代码:

https://referencesource.microsoft.com/#windowsbase/Base/System/Windows/Threading/DispatcherTimer.cs,94

if (interval.TotalMilliseconds > Int32.MaxValue)
    throw new ArgumentOutOfRangeException("interval", SR.Get(SRID.TimeSpanPeriodOutOfRange_TooLarge));

我觉得你的观察很准确。看起来也没有什么好的方法可以在不向 Microsoft 提交工单的情况下更改这种未记录的行为。

他们为什么要把那个看似人为的限制放在那里?这条线看起来足够揭示:

_dueTimeInTicks = Environment.TickCount + (int)_interval.TotalMilliseconds;

当您只需验证输入并关闭工单时,为什么要重构代码来解决极端情况? :)