2017-09-14 255 views
2

我有以下用例:我当前的线程需要做operation1,等待一些时间与其他人协调,然后需要做 operation2。在等待之间,由于文件系统事件,APC可能需要由该线程处理,这会在当前线程完成operation2之后的某个队列中添加另一个operation1以稍后处理。简单的东西像下面这样:如何使用SleepEx提供真实的睡眠时间和整体最小睡眠时间?

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

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

docs

如果参数是TRUE,并且调用该函数的线程是称为扩展I/O功能(ReadFileEx或WriteFileEx)相同的线程,在函数返回时,无论是超时期限已过或发生I/O完成回调函数时。如果发生I/O完成回调,则调用I/O完成功能。如果APC排队等待线程(QueueUserAPC),则当定时器溢出时间或APC功能被调用时,该函数返回。

从我的理解这意味着,如果SleepEx被称为和APC已排队,直接由当前线程执行,因为它能够这样做。但是之后SleepEx之后的代码会发生什么?该线程是否返回到进程operation2,因为SleepEx返回了控制权,还是该线程回到睡眠状态,并保留在SleepEx中,直到指定的时间量过去?

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

挂起当前线程,直到满足指定条件。

这可能意味着该线程被恢复,处理和装甲运兵车之后停留在SleepEx,睡了任何的时间需要:当发生以下情况之一发生时恢复执行。

如果情况并非如此,并且SleepEx确实剩下,是否说明已经过了多长时间? SleepEx似乎没有提供该值,但只有一些不变的返回值。这听起来像我需要在我自己的SleepEx之前和之后需要时间,并在一个循环中一次又一次地调用该函数,直到我真正需要的时间过去了?有没有像这样的东西,也许作为boost的一部分?

谢谢!

+0

这只是不明智的要求。如果你想最大限度地减少延迟,那么不要让它改变。拥有工作线程处理I/O完成是IOCP的标准,boost :: asio也使用它。 –

+1

if * apc *在SleepEx期间执行 - 在* apc *之后执行'SleepEx'只是返回控制。例如'SleepEx(INFINITE,TRUE)' - 返回后* apc * – RbMm

+0

@HansPassant我不想尽量减少延迟,但真的要主要等待我所要求的情况,并想知道如何处理APC使用这些的环境。使用当前的答案,人们可​​以简单地使用SleepEx而不是Sleep,并且不需要关心是否使用了APC。 –

回答

4

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

就是这样。

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