我的代码使用 System.Windows.Threading.DispatcherTimer
设置计时器。
有一天,我发现自己试图设置一个比平常更大的计时器,但我得到了一个ArgumentOutOfRangeException
:
System.ArgumentOutOfRangeException: TimeSpan period must be less than or equal to Int32.MaxValue.
但是,即使在 .NET TimeSpan
使用的 100ns 单位(“滴答”)中,我的值(大约 41 天 & 15½ 小时,或 3,598,196,944 毫秒,或 3.5981969e+13 个滴答 —不可否认,很多滴答声)应该在 64 位整数的范围内,这就是文档声称的 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]
最佳答案
当文档失败时,让我们看看旧的源代码:
if (interval.TotalMilliseconds > Int32.MaxValue)
throw new ArgumentOutOfRangeException("interval", SR.Get(SRID.TimeSpanPeriodOutOfRange_TooLarge));
在我看来,您的观察非常准确。如果不向 Microsoft 提交票证,看起来也没有什么好方法可以改变这种未记录的行为。
他们为什么要在其中设置看似人为的限制?这条线看起来足够揭示:
_dueTimeInTicks = Environment.TickCount + (int)_interval.TotalMilliseconds;
当您只需验证输入并关闭工单时,为什么要重构代码来解决极端情况? :)
关于.net - 如何让 DispatcherTimer 设置一个超过 24 天的计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60367060/