请帮助我在Windows vc ++中准确地每10秒运行以下循环。 最初,它应从诸如12:12:40:000之类的内容开始,应该忽略进行注释的工作所花费的毫秒数,并精确地每10秒在12:12:50:000等处重新开始下一个循环。
void controlloop()
{
struct timeb start, end;
while(1)
{
ftime(&start);
if(start.time %10 == 0)
break;
else
Sleep(100);
}
while(1)
{
ftime(&start);
if(start.time %10 == 0)
{
// some work here which will roughly take 100 ms
ftime(&end);
elapsedtime = (int) (1000.0 * (end.time - start.time) + (end.millitm - start.millitm));
if(elapsedtime > 10000)
{
sleeptime = 0;
}
else
{
sleeptime = 10000-(elapsedtime);
}
}
Sleep(sleeptime);
}//1
}
答案 0 :(得分:0)
Sleep
方法只能保证您睡眠至少10秒钟。之后,您的线程被认为有资格进行调度,并且在下一个数量级上,它将被再次考虑。您仍然受制于系统上任何其他线程的优先级,逻辑核心的数量等。您还受制于线程数量的分辨率,默认情况下为〜15 ms。您可以使用timeBeginPeriod
进行更改,但这会影响整个系统的功耗。
有关Windows计划的更多信息,请参见Microsoft Docs。有关电源问题的更多信息,请参见this blog post。
对于Windows,最好的选择是通过QueryPerformanceCounter
使用高频性能计数器。您使用QueryPerformanceFrequency
在周期和秒之间进行转换。
LARGE_INTEGER qpcFrequency;
QueryPerformanceFrequency(&qpcFrequency);
LARGE_INTEGER startTime;
QueryPerformanceCounter(&startTime);
LARGE_INTEGER tenSeconds;
tenSeconds.QuadPart = startTime .QuadPart + qpcFrequency.QuadPart * 10;
while (true)
{
LARGE_INTEGER currentTime;
QueryPerformanceCounter(¤tTime);
if (currentTime.QuadPart >= tenSeconds.QuadPart)
break;
}
QPC的计时器分辨率通常接近CPU处理器的循环速度。
如果您希望在尽可能使线程运行近10秒钟的同时仍使处理器使用,则:
LARGE_INTEGER qpcFrequency;
QueryPerformanceFrequency(&qpcFrequency);
LARGE_INTEGER startTime;
QueryPerformanceCounter(&startTime);
LARGE_INTEGER tenSeconds;
tenSeconds.QuadPart = startTime .QuadPart + qpcFrequency.QuadPart * 10;
while (true)
{
LARGE_INTEGER currentTIme;
QueryPerformanceCounter(¤tTIme);
if (currentTime.QuadPart >= tenSeconds.QuadPart)
{
// do a thing
tenSeconds.QuadPart = currentTime.QuadPart + qpcFrequency.QuadPart * 10;
SwitchToThread();
}
这并不是执行周期性计时器的最有效方法,但您要求的是精度而不是效率。
如果您使用的是VS 2015或更高版本,则可以使用C ++ 11类型
high_resolution_clock
,该类型使用QPC来实现。在旧版的Visual C ++中,使用了“文件系统时间”,这可以回溯到ftime
的原始分辨率问题。