C ++调用函数周期性地以微秒范围表示

时间:2013-12-31 14:08:33

标签: c++ timer precision milliseconds period

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

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

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

如何在0.5毫秒或者微秒范围内调用函数vidTimerCallback

现在,我有这样的事情:

#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)。

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我不确定你想要实现的目标,但从我所看到的情况来看,你似乎正试图制作某种自定义等待命令?

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

然后是主

中的while循环
while(1)
{
    CustomWait(500.0);
    //do stuff
}