WaitForSingleObjectEx是否允许提前唤醒?

时间:2016-07-21 15:08:50

标签: winapi synchronization

我总结了一个事件,即事件超时的WaitForSingleObjectEx没有返回"发出信号"但是超时没有通过。

具体来说,要在Qt中调试此问题,我更改了this code

bool QMutexPrivate::wait(int timeout)
{
    return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
}

到此代码(包括测量):

bool QMutexPrivate::wait(int timeout)
{
    LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
    LARGE_INTEGER Frequency;

    QueryPerformanceFrequency(&Frequency);
    QueryPerformanceCounter(&StartingTime);

    auto result = (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);

    QueryPerformanceCounter(&EndingTime);
    ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;

    ElapsedMicroseconds.QuadPart *= 1000000;
    ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
    if (!result && timeout > 0)
        std::cerr << "Waited for " << ElapsedMicroseconds.QuadPart << " microseconds when asked " << timeout << std::endl;
    return result;
}

其中event是通过CreateEvent(0, FALSE, FALSE, 0);创建的。

强调此代码路径会打印如下语句:

Waited for 96734 microseconds when asked for 100 msecs

是否允许WaitForSingleObjectEx提前唤醒,即在指定的超时之前(由于内核中的计时器合并或类似技术),或者我应该在其他地方调查我的问题? documentation并没有帮助我澄清这一点。

1 个答案:

答案 0 :(得分:4)

Wait Functions and Time-out Intervals上的MSDN:

  

指定超时间隔的准确性取决于系统时钟的分辨率。系统时钟以恒定速率“滴答”。如果超时间隔小于系统时钟的分辨率,则等待时间可能会超过指定的时间长度。如果超时间隔大于一个刻度但小于两个,则等待可以是一到两个刻度之间的任何位置,依此类推。

     

要提高等待函数的超时间隔的准确性,请调用timeGetDevCaps函数以确定支持的最小计时器分辨率,并调用timeBeginPeriod函数将计时器分辨率设置为最小值。调用timeBeginPeriod时请小心,因为频繁的调用会显着影响系统时钟,系统电源使用和调度程序。如果你调用timeBeginPeriod,请在应用程序的早期调用它一次,并确保在应用程序的最后调用timeEndPeriod函数。