在QueueUserAPC中指定的callback不会被调用

在我的代码中,我使用QueueUserAPC中断他当前工作中的主线程,以便在返回他之前的工作之前先调用一些callback。

 std::string buffer; std::tr1::shared_ptr<void> hMainThread; VOID CALLBACK myCallback (ULONG_PTR dwParam) { FILE * f = fopen("somefile", "a"); fprintf(f, "CALLBACK WAS INVOKED!\n"); fclose(f); } void AdditionalThread () { // download some file using synchronous wininet and store the // HTTP response in buffer QueueUserAPC(myCallback, hMainThread.get(), (ULONG_PTR)0); } void storeHandle () { HANDLE hUnsafe; DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hUnsafe, 0, FALSE, DUPLICATE_SAME_ACCESS); hMainThread.reset(hUnsafe, CloseHandle); } void startSecondThread () { CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AdditionalThread, 0, 0, NULL); } 

storeHandlestartSecondThread暴露给在主线程中运行的Lua解释器以及其他东西。 我现在所做的是

  1. 从我的Lua解释器中调用storeHandleDuplicateHandle返回一个非零值,因此成功。
  2. 从我的Lua解释器中调用startSecondThread 。 额外的线程正常启动, QueueUserAPC返回一个非零值,说明一切顺利。
  3. 据我了解QueueUserAPCmyCallback现在应该从主线程调用。 但是,它不。

如果QueueUserAPC是完成我的目标的正确方法(==>请参阅我的其他问题 ):

  • 我怎样才能得到这个工作?

如果我应该用其他方法来中断主线程:

  • 我应该使用其他什么方法? (请注意,我不想在主线程中使用pull -ing方法,例如WaitForSingleObject或轮询,我希望附加线程尽快将数据直接插入主线程。

Solutions Collecting From Web of "在QueueUserAPC中指定的callback不会被调用"

是的,QueueUserAPC不是这里的解决方案。 它的回调只有在线程块和程序员明确允许等待时才会运行。 这不太可能。

我不愿意发布解决方案,因为它会让你陷入巨大的麻烦。 您可以使用SuspendThread(),GetThreadContext(),SetThreadContext()和ResumeThread()来实现线程中断。 关键是将CONTEXT.Eip值保存在线程的调用堆栈中,并将其替换为中断函数的地址。

你不能做这个工作的原因是因为你会有可怕的重入问题。 你无法猜测你会中断哪个执行点。 它可能正好在它变异的状态,你需要这么严重的状态,你正在考虑这样做。 没有办法不陷入这个陷阱,你不能用一个互斥体或什么东西来阻塞它。 这也是非常难以诊断,因为它会很好地工作很长时间,然后随机失败,当中断时间恰好是不幸的。

一个线程必须处于一个众所周知的状态,才能安全地运行注入的代码。 传统的一个在之前已经提到过很多次:当一个线程正在抽取一个消息时,循环就是隐式的闲置,并且没有任何危险。 QueueUserAPC具有相同的方法,一个线程明确地向操作系统发出信号,表明它是可以安全执行回调的状态。 通过阻塞(不执行危险代码)和设置bAlertable标志。

线程必须明确表示它处于安全状态。 没有安全的推送模式,只有拉。

从我在MSDN中可以理解的,直到线程进入可警告状态,调用SleepExSignalObjectAndWaitWaitForSingleObjectEx, WaitForMultipleObjectsExMsgWaitForMultipleObjectsEx SignalObjectAndWait调用SignalObjectAndWait

所以如果你真的不想做一些投票,我不认为这个方法适合你的情况。

是否有可能在你的主线程中实现一个“消息泵”(或者说是一个事件监听器),并把所有当前的工作委托给另一个线程? 在这种情况下,主线程等待由其他线程设置的任何事件。