C++ 如何将SleepEx与alertable true和总体最小睡眠时间结合使用?

C++ 如何将SleepEx与alertable true和总体最小睡眠时间结合使用?,c++,windows,multithreading,winapi,sleep,C++,Windows,Multithreading,Winapi,Sleep,我有以下用例:我的当前线程需要执行操作1,等待一段时间与其他线程协调,然后需要执行 操作2。在等待之间,APC可能需要由该线程处理,因为文件系统事件会将另一个operation1添加到某个队列,以便在当前线程完成operation2后处理。简单的如下所示: while (true) { processOperation1; SleepEx(..., true); processOperation2; } 重要的是,在operation1和operation2之间,必须至少经过Sle

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

while (true)
{
  processOperation1;
  SleepEx(..., true);
  processOperation2;
}
重要的是,在
operation1
operation2
之间,必须至少经过
SleepEx
的指定时间!这不需要是一个整体,线程可以立即用于处理APC并对另一个
操作1
排队,除非经过指定的时间,否则它不应该继续
操作2

从:

如果参数为TRUE,且调用此函数的线程与调用扩展I/O函数(ReadFileEx或WriteFileEx)的线程相同,则当超时时间已过或出现I/O完成回调函数时,该函数将返回。如果发生I/O完成回调,则调用I/O完成函数。如果一个APC被排队到线程(QueueUserAPC),则该函数在计时器超时或调用APC函数时返回

根据我的理解,这意味着如果调用了
SleepEx
,并且一个APC已经排队,那么它将直接由当前线程执行,因为它能够这样做。但是在
SleepEx
之后的代码会发生什么呢?线程返回到进程
operation2
是因为
SleepEx
返回了控件,还是返回到睡眠状态,一直保持在
SleepEx
中,直到指定的时间过去

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

挂起当前线程,直到满足指定的条件。当发生以下情况之一时,将继续执行:

这可能意味着线程将被恢复,处理APCs,然后停留在
SleepEx
,睡眠所需的时间

如果情况并非如此,并且
SleepEx
真的离开了,它能告诉我们经过了多少时间吗
SleepEx
似乎没有提供该值,但只提供了一些常量返回值。这听起来像是我需要自己在
SleepEx
之前和之后花费一些时间,并在循环中一次又一次地调用该函数,直到我真正需要的时间过去了?已经有这样的东西了吗,也许是作为
boost
的一部分


谢谢

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

像这样的

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

这不是一个合理的要求。如果你想最小化延迟,那么不要改变它。让工作线程处理I/O完成是当今IOCP的标准,boost::asio也使用它。如果apc在
SleepEx
-apc
SleepEx
之后执行,只需返回控制即可。例如
SleepEx(无限,真)
-返回后apc@HansPassant我不想最小化延迟,但我真的想主要在我要求的情况下等待,并想知道如何在使用这些延迟的环境中处理APC。根据目前的答案,您可以简单地使用SleepEx而不是Sleep always,并且不需要关心是否使用了APC。通常,您需要关心是否正在使用APC,因为如果APC正在使用,则执行可警报的等待可能不安全。特别是,如果执行等待的函数是从APC内部调用的,则可能会遇到问题。根据你在问题中所说的,我认为这对你来说不是问题,但我想我应该提一下以防万一。PS:根据你的情况,processOperation1()和processOperation2()作为APC本身可能更为优雅,processOperation2()通过一个调用。