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

标签 .net c++-cli

我的代码使用 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]

最佳答案

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

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;

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

关于.net - 如何让 DispatcherTimer 设置一个超过 24 天的计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60367060/

相关文章:

c++ - 视觉 C++ : how to pass pointer to array as parameter?

c++-cli - C++/CLI 包装器不工作(LoaderLock 异常)

c++ - 将文本框字符串转换为 float ?

.net - C++/CLI 委托(delegate)作为函数指针 (System.AccessViolationException)

c# - 如何更改计划任务的内存优先级?

c# - 从 C++ 传递函数指针以供 C# 调用 - 函数的参数包括一个宽字符字符串 (LPCWSTR)

.net - 如何在单元测试VB.net期间禁止弹出消息框

c# - 具有多个计时器的 Windows 服务

c# - 如何在将 HTML 从 abcpdf 转换为 PDF 时加载外部图像

.net - vstest.console.exe执行模型和隔离行为