我正在尝试执行具有稳定循环时间(例如20ms)的方法。我目前的方法是使用std::thread
创建一个线程。在这个线程中,我执行以下操作(伪代码):
while(true)
{
tStart = GetCurrentTime();
ExecuteMethod();
tEnd = GetCurrentTime();
actualCycleTime = tEnd - tStart;
SleepFor(DesiredCycleTime - actualCycleTime);
}
对于时间测量和睡眠,我使用std::chrono
(std::steady_clock
和std::thread::sleep_for
)。
问题是我的循环没有在预期的稳定20ms运行。相反,我的循环时间在20到60毫秒之间。我的猜测是,这是由Windows调度程序引起的。
有没有更好的方法来实现稳定的循环时间(忙碌等待等)?
答案 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);
}