我可以从Windows-API的睡眠功能中得到期望吗?

问题描述 投票:0回答:1

[我试图在CPP中为Windows创建一个简单的图形程序(我的机器上装有Windows 10,并且我正在努力锁定帧速率。

这是我的问题的简单说明:

inline LARGE_INTEGER
get_wall_clock()
{
    LARGE_INTEGER result;
    QueryPerformanceCounter(&result);
    return result;
}

static LARGE_INTEGER frequency;

inline float
get_seconds_elapsed(LARGE_INTEGER begin, LARGE_INTEGER end)
{
    return (float)(end.QuadPart - begin.QuadPart) / (float)frequency.QuadPart;
}

int main()
{
    bool can_sleep = (timeBeginPeriod(1) == TIMERR_NOERROR);
    QueryPerformanceFrequency(&frequency);
    int target_HZ = 60;
    float target_seconds_per_frame = 1.0f / (float)target_HZ;
    LARGE_INTEGER last_counter = get_wall_clock();
    while(true)
    {
        do_something();

        LARGE_INTEGER end_frame = get_wall_clock();
        float seconds_of_work = get_seconds_elapsed(last_counter, end_frame);
        float seconds_of_frame = seconds_of_work;
        if(seconds_of_work < target_seconds_per_frame)
        {
            if(can_sleep)
            {
                int ms_to_sleep = (int)(1000.0f * (target_seconds_per_frame - seconds_of_work));
                if(ms_to_sleep)
                {
                    Sleep(ms_to_sleep);
                }
            }
            float frame_duration = get_seconds_elapsed(last_counter, get_wall_clock());
            Assert(frame_duration < target_seconds_per_frame);
            while(seconds_of_frame < target_seconds_per_frame)
                seconds_of_frame = get_seconds_elapsed(last_counter, get_wall_clock());
        }
        last_counter = get_wall_clock();
    }
    timeEndPeriod(1);
}

我的问题是断言:

Assert(frame_duration < target_seconds_per_frame);

几乎总是在开火。

[我试图对睡眠的毫秒数进行一些调整,甚至调整了睡眠时间,使其只能睡眠所需的90%的毫秒-但这似乎没有帮助。

但是真正的奇怪之处是以下...当我尝试通过以下方法测量Sleep函数实际睡眠的时间时:

LARGE_INTEGER sleep_start = get_wall_clock();
Sleep(ms_to_sleep);
float seconds_slept = get_seconds_elapsed(sleep_start, get_wall_clock());

我发现有时它会睡[[waaayyy超过要求的毫秒数。看到相差10到20毫秒的情况并不少见(我有一次ms_to_sleep为12,实际上它睡了30毫秒以上)。

有没有明显的我想念的地方?我知道根据文档,不能保证在要求的时间内睡眠,但是我认为timeBeginPeriod + ms_to_sleep的地板可以覆盖...

还有其他方法可以可靠地等待帧结束(不仅仅是循环)?

预先感谢你们...

c++ windows sleep frame-rate msdn
1个回答
0
投票
有什么明显的地方我想念吗?

坦白说,是的。您没有阅读手册。从docs

经过睡眠间隔后,线程准备运行。如果指定0毫秒,则线程将放弃其时间片的其余部分,但保持就绪状态。

请注意,不能保证就绪线程可以立即运行。因此,线程可能要等到睡眠间隔过后的一段时间才能运行。有关更多信息,请参阅安排优先级。

Sleep不能完全按照您要求的时间睡觉。
© www.soinside.com 2019 - 2024. All rights reserved.