4

我在这里做错了什么 WaitForThreadpoolWaitCallbacks 立即返回而不等待?

HANDLE hEvent = CreateEvent(0, FALSE, FALSE, 0);
...
PTP_WAIT Pwa = CreateThreadpoolWait(WaitCallback, NULL, NULL);
SetThreadpoolWait(Pwa, hEvent, NULL);
// Here we should wait until hEvent gets signaled
WaitForThreadpoolWaitCallbacks(Pwa, FALSE);
// Here we should get after hEvent gets signaled

WaitForThreadpoolWaitCallbacks 从不等待,在 WaitForThreadpoolWaitCallbacks 之后继续执行。但是,如果事件发出信号,回调仍然会以任何方式被调用。无论之前是否调用了 WaitForThreadpoolWaitCallbacks,该事件也会发出信号。

在 SetThreadPoolWait Timeout 设置为 NULL 以永远等待。

指向 FILETIME 结构的指针,该结构指定等待操作应超时的绝对或相对时间。如果该参数指向一个正值,它表示从 1601 年 1 月 1 日(UTC)开始的绝对时间,以 100 纳秒为间隔。如果此参数指向负值,则表示相对于当前时间要等待的时间量。有关时间值的详细信息,请参阅文件时间。

如果此参数指向 0,则等待立即超时。如果此参数为 NULL,则等待不会超时。

编辑:似乎单独调用SetThreadpoolWait不会将线程池等待项(PTP_WAIT)设置为挂起状态。如果是这种情况,WaitForThreadpoolWaitCallbacks如果 CancelPendingCallbacks 参数设置为 FALSE,将等待。“取消挂起”一词也可能具有误导性。挂起也可能意味着一直在等待的事件已经发出信号,但是没有空闲的工作线程来启动回调方法。

另一个不太可能的原因可能WaitForThreadpoolWaitCallbacks是越野车。

4

1 回答 1

0

似乎可能存在竞争条件:

来自MSDN 杂志

问题是等待对象只会在关联同步对象发出信号或超时到期时排队回调。在其中一个事件发生之前,没有回调排队,等待函数也没有什么可以等待的。解决方法是先用空指针值调用 SetThreadpoolWait,告诉等待对象停止等待,然后调用 WaitForThreadpoolWaitCallbacks 以避免任何竞争条件:

SetThreadpoolWait(w.get(), nullptr, nullptr);
WaitForThreadpoolWaitCallbacks(w.get(), TRUE);
于 2020-04-06T23:04:39.230 回答