2

I have hand-made thread pool. Threads read from completion port and do some other stuff. One particular thread has to be ended. How to interrupt it's waiting if it hangs on GetQueuedCompletionStatus() or GetQueuedCompletionStatusEx()?

  • Finite timeout (100-1000 ms) and exiting variable are far from elegant, cause delays and left as last resort.
  • CancelIo(completionPortHandle) within APC in target thread causes ERROR_INVALID_HANDLE.
  • CancelSynchronousIo(completionPortHandle) causes ERROR_NOT_FOUND.
  • PostQueuedCompletionStatus() with termination packet doesn't allow to choose thread.
  • Rough TerminateThread() with mutex should work. (I haven't tested it.) But is it ideologically good?
  • I tried to wait on special event and completion port. WaitForMultipleObjects() returned immediately as if completion port was signalled. GetQueuedCompletionStatus() shows didn't return anything.

I read Overlapped I/O: How to wake a thread on a completion port event or a normal event? and googled a lot.

Probably, the problem itself – ending thread's work – is sign of bad design and all my threads should be equal and compounded into normal thread pool. In this case, PostQueuedCompletionStatus() approach should work. (Although I have doubts that this approach is beautiful and laconic especially if threads use GetQueuedCompletionStatusEx() to get multiple packets at once.)

4

2 回答 2

3

如果您只想减小线程池的大小,则退出哪个线程并不重要。

但是,如果由于某种原因您需要向特定线程发出信号,它需要退出,而不是允许任何线程退出,您可以使用此方法。

如果您使用,您可以通过传递forGetQueuedCompletionStatusEx来进行警报等待。然后,您可以使用将 APC 排队到要退出的线程。TRUEfAlertableQueueUserAPC

如果线程很忙,那么您仍然需要等待当前工作项完成。

当然不要调用 TerminateThread。

于 2015-10-03T11:06:34.317 回答
1

不幸的是,I/O 完成端口句柄始终处于信号状态,因此不能真正在WaitFor*函数中使用。

GetQueuedCompletionStatus[Ex]是在完成端口上阻塞的唯一方法。对于空队列,只有当线程被警告时,函数才会返回。正如@Ben 所提到的,这QueueUserAPC将使线程发出警报并导致GetQueuedCompletionStatus返回。

但是,QueueUserAPC分配内存,因此在内存不足的情况下或内存配额生效时可能会失败。对于PostQueuedCompletionStatus. 因此,在退出路径上使用这些函数中的任何一个都不是一个好主意。

不幸的是,唯一可靠的方法似乎是调用无证NtAlertThread导出的ntdll.dll.

extern "C" NTSTATUS __stdcall NtAlertThread(HANDLE hThread);

与 链接ntdll.lib。此函数将使目标线程进入警报状态,而无需排队。

于 2019-10-08T16:23:54.417 回答