稳定的循环时间

时间:2017-07-06 05:02:14

标签: c++ winapi stl

我正在尝试执行具有稳定循环时间(例如20ms)的方法。我目前的方法是使用std::thread创建一个线程。在这个线程中,我执行以下操作(伪代码):

while(true)
{
  tStart = GetCurrentTime();
  ExecuteMethod();
  tEnd = GetCurrentTime();

  actualCycleTime = tEnd - tStart;
  SleepFor(DesiredCycleTime - actualCycleTime);
}

对于时间测量和睡眠,我使用std::chronostd::steady_clockstd::thread::sleep_for)。

问题是我的循环没有在预期的稳定20ms运行。相反,我的循环时间在20到60毫秒之间。我的猜测是,这是由Windows调度程序引起的。

有没有更好的方法来实现稳定的循环时间(忙碌等待等)?

1 个答案:

答案 0 :(得分:2)

您可以使用计时器事件。如果您需要一个非常可靠的时钟,则需要将优先级提高到最大值。此代码将为用户模式应用程序提供最佳性能。为清楚起见,我省略了通常的错误检查,但我已经标记了应该检查的调用。如有疑问,请咨询MSDN。

Windows计时器分辨率仅限于Windows用于在线程之间切换的全局时间片。在现代CPU上,该值通常为2-5ms。在较旧的CPU上,此值为10-15ms。您可以控制此全局设置 通过调用timeBeginPeriod()。这将影响中断的精度。

// use this event to exit the loop, by calling SetEvent(hExitEvent).
HANDLE hExitEvent = CreateEvent(NULL, NULL, FALSE, NULL);  

void RealTimeLoop()
{
    // You may want to raise the process priority...
    HANDLE hProcess = GetCurrentProcess();                       // never fails
    SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);

    // setting the priority is critical.
    HANDLE hThread = GetCurrentThread();                         // never fails
    SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);   // could fail

    timeBeginPeriod(1);                                          // could fail

    HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);      // could fail

    // could also set a call back here, but I've never tried it.
    LARGE_INTEGER dueTime = {};
    SetWaitableTimer(hTimer, &dueTime, 20, NULL, NULL, FALSE);   // could fail

    HANDLE ah[2] = { hExitEvent, hTimer };
    bool exitLoop = false;

    while(!exitLoop)
    {
        switch (WaitForMultipleObjects(2, ah, FALSE, INFINITE))
        {
            default:  // error would arrive here 
            case 0:  exitLoop = true; break;
            case 1:  ExecuteMethod(); break;
        }
   }
   timeEndPeriod(1);
   CloseHandle(hTimer);
   CloseHandle(hThread);
   CloseHandle(hProcess);
}