【问题标题】:C++ Call Function Periodically in Microseconds RangeC++ 在微秒范围内定期调用函数
【发布时间】:2013-12-31 14:08:32
【问题描述】:

在 C++ 中,我可以使用 Windows 多媒体计时器在 毫秒 范围内定期调用函数,如下所示:

timeSetEvent(intPeriod_Milliseconds, 0, vidTimerCallback, ...., TIME_PERIODIC )

其中intPeriod_Milliseconds 是一个整数变量,所需周期以毫秒为单位。

如何让函数 vidTimerCallback 每 0.5 毫秒或微秒范围内被调用一次?

现在,我有这样的事情:

#include <windows.h>

double PCFreq = 0.0;
__int64 CounterStart = 0;

void StartCounter()
{
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
    cout << "QueryPerformanceFrequency failed!\n";

    PCFreq = double(li.QuadPart)/1000.0;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
}
double GetCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return double(li.QuadPart-CounterStart)/PCFreq;
}

int main()
{
    StartCounter();
    Sleep(1000);
    cout << GetCounter() <<"\n"; //It prints accurate time like 998
    return 0;
}

但我无法进一步改进它以定期调用函数。 我使用 here 类有类似的情况。

另外,我有一些很好用的东西,但它适用于 C# 而不是 C++ (here)。

【问题讨论】:

  • @DavidHeffernan 我想我已经通过调用 timeSetEvent 来做到这一点,它需要 毫秒 周期的 integer 输入。
  • 抱歉,我正在查看您提供的不使用计时器的程序。
  • @MadScienceDreams 我发布了三个示例,告诉我有办法实现这一目标。

标签: c++ timer precision milliseconds period


【解决方案1】:

该 C# 代码使用热等待循环来测量时间。 .NET Stopwatch 类是 QueryPerformanceCounter() 的包装器,您也可以使用它。 Thread.SpinWait() 方法是 YieldProcessor() 的包装器,您也可以使用它。参数只是你调用它的次数,使用 10 是相当随意的。

请记住,这不是线程调度程序知道的自旋等待。就它而言,你正在燃烧你的线程量子而没有屈服。当然你是,那个核心并没有做任何非常有用的事情。 YieldProcessor() 只是通过执行 PAUSE 指令来避免使处理器着火。结果是当机器加载并且其他线程竞争 CPU 服务时,您的计时器将表现不佳。你的线程在烧完它的量子后会进入狗屋一段时间,45毫秒是很正常的。请确保这不是有害的,几乎总是如此。提高线程优先级有点帮助,你仍然无法与内核线程竞争。尤其是视频和音频驱动程序会让你头痛。

多媒体定时器没有这个问题,当然你不能低于1毫秒。您应该在所有现代版本的 Windows 上使用 CreateTimerQueueTimer(),它不会受到调用 timeBeginPeriod() 的miserable side-effects 的影响。强烈建议通过热等待循环。

【讨论】:

    【解决方案2】:

    你不能。 Windows 不是实时操作系统,因此即使它具有接受微秒参数的功能,或者您要在 Windows 之上设计自己的调度程序,您仍然无法以这样的速率执行某些功能。事实上,据我所知,Windows 不保证对何时唤醒特定线程有任何真正的执行硬限制。通常它以大约 15 毫秒的分辨率运行,因此除非您在应用中的某个位置调用 TimeBeginPeriod(1),否则要求 Windows 执行 Sleep(1) 很可能会休眠 15 毫秒。

    【讨论】:

    • 对不起。调用 TimeBeginPeriod 会缩短电池寿命?没有意识到这一点。
    【解决方案3】:

    我不确定您要达到什么目的,但从我所见,您似乎正在尝试制作某种自定义等待命令?

    void CustomWait(double MStoWait)
    {
        double StartCount = double( GetCounter() + MStoWait );
        while(GetCounter() <= StartCount) {}
        printf("%f\n" ,GetCounter()); 
    }
    

    然后是main中的while循环

    while(1)
    {
        CustomWait(500.0);
        //do stuff
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-03
      • 2013-12-08
      • 2014-05-31
      • 2014-07-07
      • 1970-01-01
      • 2012-04-19
      • 2018-01-26
      • 1970-01-01
      • 2020-09-09
      相关资源
      最近更新 更多