代码之家  ›  专栏  ›  技术社区  ›  Etan bbum

在QueueUserAPC中指定的回调未被调用

  •  4
  • Etan bbum  · 技术社区  · 16 年前

    QueueUserAPC 打断 从他当前的工作中删除主线程,以便在返回到以前的工作之前首先调用一些回调。

    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);
    }
    

    storeHandle startSecondThread 与主线程中运行的Lua解释器以及其他内容一起公开。我现在做的是

    1. 援引 店柄 来自我的Lua翻译。 DuplicateHandle
    2. startSecondThread 来自我的Lua翻译。附加线程正确启动,并且 返回一个非零值,表示一切正常。
    3. QueueUserAPC myCallback 现在应该从主线程调用。然而,事实并非如此。

    如果 QueueUserAPC question ):

    • 我怎样才能让它工作?

    如果我需要其他方法来中断主线程:

    • 我还应该用什么方法(请注意,我不想使用 -在主线程中为这类应用程序设置 WaitForSingleObject 或者投票。我想要额外的线程
    2 回复  |  直到 9 年前
        1
  •  12
  •   Hans Passant    16 年前

    是的,QueueUserAPC不是这里的解决方案。它的回调仅在线程阻塞且程序员明确允许等待发出警报时运行。那不太可能。

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

    线程必须处于已知状态才能安全运行注入的代码。传统的方法以前已经被多次提到:当线程在泵送消息时,消息循环隐式地处于空闲状态,并且没有做任何危险的事情。QueueUserAPC有相同的方法,线程显式地向操作系统发出信号,表明它是可以安全执行回调的状态。通过阻塞(不执行危险代码)和设置可打捆标志。

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

        2
  •  4
  •   cedrou    16 年前

    MSDN ,在线程进入可警报状态之前不会调用回调,这是通过调用 SleepEx SignalObjectAndWait , WaitForSingleObjectEx, WaitForMultipleObjectsEx MsgWaitForMultipleObjectsEx .

    所以,如果你真的不想做一些民意调查,我认为这种方法不适合你的情况。