Winapi 如何强制GetQueuedCompletionStatus()立即返回?
我有手工做的线池。线程从完成端口读取数据并执行其他操作。必须结束一个特定的线程。如果它挂起GetQueuedCompletionStatus()或GetQueuedCompletionStatusEx(),如何中断它的等待Winapi 如何强制GetQueuedCompletionStatus()立即返回?,winapi,io-completion-ports,Winapi,Io Completion Ports,我有手工做的线池。线程从完成端口读取数据并执行其他操作。必须结束一个特定的线程。如果它挂起GetQueuedCompletionStatus()或GetQueuedCompletionStatusEx(),如何中断它的等待 有限超时(100-1000毫秒)和退出变量远远不够优雅,会导致延迟,并将其作为最后手段 目标线程中APC内的CancelIo(completionPortHandle)导致错误\u无效\u句柄 CancelSynchronousIo(completionPortHandle
- 有限超时(100-1000毫秒)和退出变量远远不够优雅,会导致延迟,并将其作为最后手段
- 目标线程中APC内的CancelIo(completionPortHandle)导致
错误\u无效\u句柄
- CancelSynchronousIo(completionPortHandle)导致
错误\u未找到
- 带有终止数据包的PostQueuedCompletionStatus()不允许选择线程
- 带有互斥对象的粗糙TerminateThread()应该可以工作。(我没有测试过。)但它在意识形态上好吗
- 我试图等待特殊事件和完成端口
立即返回,就像发送了完成端口信号一样<代码>GetQueuedCompletionStatus()显示未返回任何内容WaitForMultipleObjects()
也许,问题本身——结束线程的工作——是糟糕设计的标志,我所有的线程都应该是平等的,并组合到正常的线程池中。在这种情况下,PostQueuedCompletionStatus()方法应该可以工作。(尽管我怀疑这种方法是否美观简洁,特别是当线程使用GetQueuedCompletionStatusEx()一次获取多个数据包时。)如果您只想减小线程池的大小,那么退出哪个线程并不重要 但是,如果出于某种原因,您需要向特定线程发出需要退出的信号,而不是允许任何线程退出,则可以使用此方法 如果您使用
GetQueuedCompletionStatusEx
,您可以通过为fAlertable
传递TRUE
来执行可警报的等待。然后,可以使用QueueUserAPC
将APC排队到要退出的线程
当然不要叫TerminateThread 不幸的是,I/O完成端口句柄始终处于信号状态,因此不能真正用于
WaitFor*
函数中
GetQueuedCompletionStatus[Ex]
是在完成端口上进行阻止的唯一方法。对于空队列,只有当线程发出警报时,函数才会返回。正如@Ben所提到的,QueueUserAPC
将使线程发出警报,并导致GetQueuedCompletionStatus
返回
但是,QueueUserAPC
分配内存,因此在内存不足或内存配额有效时可能会失败。PostQueuedCompletionStatus
也是如此。因此,在退出路径上使用这些函数中的任何一个都不是一个好主意
不幸的是,唯一可靠的方法似乎是调用由ntdll.dll
导出的未记录的ntalerthread
extern "C" NTSTATUS __stdcall NtAlertThread(HANDLE hThread);
链接到
ntdll.lib
。此函数将使目标线程进入警报状态,而无需排队。“Rough TerminateThread”:在终止时,您无法真正知道线程已挂起。所以它是不安全的。为什么你需要选择一个特定的线程?@usr的确,即使我将数据包处理代码和终止调用包装在互斥锁中,刚从队列中取出但尚未开始处理的数据包也可能丢失。@Ben“just don't”是我所说的“思想上”。你的两个建议都有问题。你不想取消IO,你只想线程退出,对吗?最好是在APC内设置一个标志。当GetQueuedCompletionStatusEx返回时,您必须检查返回代码(因为如果有APC,则可能没有任何工作),然后检查标志以查看是否必须退出。啊,我忘了说事件。我会更新并回答。简而言之,WaitForMultipleObjects
立即返回,就好像完成端口发出了信号,但GetQueuedCompletionStatus()没有返回任何内容。我试图执行空APC,结果导致等待返回!我仍然不知道这是对还是错,但似乎还可以。我已经多次阅读了fAlertable的TRUE value是什么意思的语句:当系统将I/O完成例程或APC排队给线程时,线程返回,线程执行该函数。谢谢。是的,没错。一个可报警的等待将执行APC,然后返回,无论IO完成是否可用。