如何在Windows vc ++中每10秒精确执行一次while循环

时间:2020-04-11 08:09:42

标签: visual-c++ time while-loop milliseconds

请帮助我在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  
}

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(&currentTime);

    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(&currentTIme);

    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的原始分辨率问题。