如何让 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 TimeSpan
s 使用的 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]
当文档失败时,让我们看一下旧的源代码:
if (interval.TotalMilliseconds > Int32.MaxValue)
throw new ArgumentOutOfRangeException("interval", SR.Get(SRID.TimeSpanPeriodOutOfRange_TooLarge));
我觉得你的观察很准确。看起来也没有什么好的方法可以在不向 Microsoft 提交工单的情况下更改这种未记录的行为。
他们为什么要把那个看似人为的限制放在那里?这条线看起来足够揭示:
_dueTimeInTicks = Environment.TickCount + (int)_interval.TotalMilliseconds;
当您只需验证输入并关闭工单时,为什么要重构代码来解决极端情况? :)
我的代码使用 System.Windows.Threading.DispatcherTimer
设置计时器。
有一天我发现自己试图设置一个比平时更大的计时器,结果我得到了一个 ArgumentOutOfRangeException
:
System.ArgumentOutOfRangeException: TimeSpan period must be less than or equal to Int32.MaxValue.
然而,即使在 .NET TimeSpan
s 使用的 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]
当文档失败时,让我们看一下旧的源代码:
if (interval.TotalMilliseconds > Int32.MaxValue)
throw new ArgumentOutOfRangeException("interval", SR.Get(SRID.TimeSpanPeriodOutOfRange_TooLarge));
我觉得你的观察很准确。看起来也没有什么好的方法可以在不向 Microsoft 提交工单的情况下更改这种未记录的行为。
他们为什么要把那个看似人为的限制放在那里?这条线看起来足够揭示:
_dueTimeInTicks = Environment.TickCount + (int)_interval.TotalMilliseconds;
当您只需验证输入并关闭工单时,为什么要重构代码来解决极端情况? :)