如何使用具有警报的真实睡眠时间和整体最小睡眠时间的SleepEx?

时间:2017-09-14 13:45:03

标签: c++ windows multithreading winapi sleep

我有以下用例:我当前的线程需要做operation1,等待一段时间与其他人协调,然后需要做 operation2。在等待之间,由于文件系统事件,可能需要由该线程处理APC,这会将另一个operation1添加到某个队列,以便在当前线程完成operation2之后处理。简单如下:

while (true)
{
  processOperation1;
  SleepEx(..., true);
  processOperation2;
}

重要的是,在operation1operation2之间至少必须经过SleepEx指定的时间!这不需要是一个整体,线程可以立即用于处理APC并排队另一个operation1,它不应该继续operation2,除非指定的时间量已经过去。

来自docs

  

如果参数为TRUE并且调用此函数的线程与调用扩展I / O函数(ReadFileEx或WriteFileEx)的线程相同,则该函数在超时时间段或I / O时返回O完成回调功能。如果发生I / O完成回调,则调用I / O完成功能。如果APC排队到线程(QueueUserAPC),则该函数在超时时间或调用APC函数时返回。

根据我的理解,这意味着如果调用SleepEx并且APC已经排队,则由当前线程直接执行,因为它能够这样做。但是之后SleepEx之后的代码会发生什么?线程是否返回进程operation2,因为SleepEx返回控制或线程是否重新进入休眠状态,保持在SleepEx直到指定的时间量过去?

文档中的第一句话不是关于从函数返回,而是“恢复线程”:

  

暂停当前线程,直到满足指定条件。发生以下任一情况时,执行将恢复:

这可能意味着线程恢复,处理APC,之后停留在SleepEx,无论需要多长时间都在睡眠。

如果不是这种情况并且SleepEx真的离开了,它会告诉我们已经过了多长时间吗? SleepEx似乎没有提供该值,而只提供一些常量返回值。这听起来像我需要在SleepEx之前和之后花费时间并在循环中一次又一次地调用该函数,直到我需要的时间真的过去了?是否有类似的东西,可能是boost的一部分?

谢谢!

1 个答案:

答案 0 :(得分:4)

您应该在循环中调用SleepEx并处理排队的APC,直到超过所需的超时时间。

像这样。

for (DWORD dwStart = GetTickCount(); ; )
{
    DWORD dwElapsed = GetTickCount() - dwStart;
    DWORD dw = (dwTimeout > dwElapsed) ? (dwTimeout - dwElapsed) : 0;
    if (!SleepEx(dw, TRUE))
        break;
}