【问题标题】:How to setup timer resolution to 0.5 ms?如何将定时器分辨率设置为 0.5 毫秒?
【发布时间】:2010-06-29 14:20:28
【问题描述】:

我想将机器计时器分辨率设置为 0.5 毫秒。

Sysinternal 实用程序报告最小时钟分辨率为 0.5 毫秒,因此可以完成。

附:我知道如何将其设置为 1 毫秒。

P.P.S.我把它从 C# 改成了更一般的问题(感谢 Hans)

系统计时器分辨率

【问题讨论】:

  • 您可以查看here 了解有关计时器设置和亚毫秒级计时器服务的详细信息。

标签: c++ windows winapi timer driver


【解决方案1】:

NtSetTimerResolution

示例代码:

#include <windows.h>

extern "C" NTSYSAPI NTSTATUS NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);

...

ULONG currentRes;
NtSetTimerResolution(5000, TRUE, &currentRes);

链接ntdll.lib

【讨论】:

    【解决方案2】:

    可以通过隐藏的 API NtSetTimerResolution() 获得 0.5 毫秒 的分辨率。 NtSetTimerResolution 由本机 Windows NT 库 NTDLL.DLL 导出。请参阅 MSDN 上的 How to set timer resolution to 0.5ms ?。然而,真正可实现的分辨率取决于底层硬件。现代硬件确实支持 0.5 毫秒的分辨率。 在Inside Windows NT High Resolution Timers 中可以找到更多详细信息。支持的分辨率可以通过调用 NtQueryTimerResolution() 获得。

    怎么做:

    #define STATUS_SUCCESS 0
    #define STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000245
    
    // after loading NtSetTimerResolution from ntdll.dll:
    
    // The requested resolution in 100 ns units:
    ULONG DesiredResolution = 5000;  
    // Note: The supported resolutions can be obtained by a call to NtQueryTimerResolution()
    
    ULONG CurrentResolution = 0;
    
    // 1. Requesting a higher resolution
    // Note: This call is similar to timeBeginPeriod.
    // However, it to to specify the resolution in 100 ns units.
    if (NtSetTimerResolution(DesiredResolution ,TRUE,&CurrentResolution) != STATUS_SUCCESS) {
        // The call has failed
    }
    
    printf("CurrentResolution [100 ns units]: %d\n",CurrentResolution);
    // this will show 5000 on more modern platforms (0.5ms!)
    
    //       do your stuff here at 0.5 ms timer resolution
    
    // 2. Releasing the requested resolution
    // Note: This call is similar to timeEndPeriod 
    switch (NtSetTimerResolution(DesiredResolution ,FALSE,&CurrentResolution) {
        case STATUS_SUCCESS:
            printf("The current resolution has returned to %d [100 ns units]\n",CurrentResolution);
            break;
        case STATUS_TIMER_RESOLUTION_NOT_SET:
            printf("The requested resolution was not set\n");   
            // the resolution can only return to a previous value by means of FALSE 
            // when the current resolution was set by this application      
            break;
        default:
            // The call has failed
    
    }
    

    注意:NtSetTImerResolution 的功能基本上通过使用布尔值Set 映射到函数timeBeginPeriod timeEndPeriod(有关该方案的更多详细信息,请参阅Inside Windows NT High Resolution Timers 和所有其影响)。但是,多媒体套件将粒度限制为毫秒,而 NtSetTimerResolution 允许设置亚毫秒值。

    【讨论】:

    • 谢谢。那是我 4 年前发现的……但是由于一连串的敌意和误导性的答案,我自己回答了,但尽可能简短(因为显然没有人需要这个)。我很高兴在我的实时软件中使用它,因为(根据大多数“开发人员”,这是不可能在 Windows 和 .net 上编写的).. PS 我看了你的项目。看起来很有希望.. 只需注意 Windows 计时器'抖动'.. 你的项目比我的更具挑战性!祝你好运!
    • 根据我的实验,我认为 STATUS_TIMER_RESOLUTION_NOT_SET 错误代码应该是 0xC0000245 而不是 245
    • @RolandPihlakas 是的,谢谢。我已经编辑了我的答案以纠正这个问题。其实就是documented at MSDN这样的。
    【解决方案3】:

    如果你使用python,我写了一个名为wres的库,它内部调用了NtSetTimerResolution。

    pip install wres

    import wres
    
    # Set resolution to 0.5 ms (in 100-ns units)
    # Automatically restore previous resolution when exit with statement
    with wres.set_resolution(5000):
        pass
    

    【讨论】:

    • 也许在这篇文章中添加更多细节会对 OP 和整个社区更有帮助。
    【解决方案4】:

    使用 timeBeginPeriod 和 timeSetEvent 可以得到最好的 Win32 API 是 1 毫秒。也许你的 HAL 可以做得更好,但那是学术性的,你不能用 C# 编写设备驱动程序代码。

    【讨论】:

    • 我已经用过那些了。我希望能做到这一点。你知道是否有一个可以做到这一点的实用程序(在 C# 中不一定)。毕竟我只需要更改系统时钟。
    • 我从 C# 更改为其他任何东西。无论如何都需要这样做。
    【解决方案5】:

    你需要一个高分辨率的计时器。你可以在这里找到一些信息:http://www.codeproject.com/KB/cs/highperformancetimercshar.aspx

    编辑:可以在此处找到更多信息:设置为十分之一毫秒; http://msdn.microsoft.com/en-us/library/aa964692(VS.80).aspx

    【讨论】:

    • 在 System.dll 中被 System.Diagnostics.Stopwatch 取代。
    • @Charlie Salts:我猜这是 Bobb 正在寻找的课程 (+1)
    • 我不想测量时间我只需要它滴答作响。
    • 为什么不使用上面的类构建自己的 timercontrol - 添加了一篇新的 MSDN 文章。这种计时的大多数解决方案都不适用于事件,而是两个“状态”之间经过的时间。
    猜你喜欢
    • 1970-01-01
    • 2012-11-12
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    相关资源
    最近更新 更多