KeyHook在另一个线程中

时间:2012-07-07 12:01:26

标签: c# multithreading hook keyboard-hook setwindowshookex

在我的C#应用​​程序中,我想做keyhook,但是,在按下键时调用的方法在另一个线程中调用。这样就不会发生,我的程序省略了一个键,因为我的应用程序忙于其他事情。我怎样才能在另一个线程中创建它?我发现信息,根据我创建钩子的线程,在按下键时调用的方法将在该线程中调用,但这不会发生。无论我挂钩它的线程如何,总是在主线程中调用此方法。请帮忙。这是我的代码的大纲:

int HookProc(int code, int wParam, ref lParamStruct lParam)
{
    // ... this should be invoked in another thread - thread th, which I use to call SetWindowsHook
}
void SetWindowsHook()
{
    lpMsg msg = new lpMsg();

    PeekMessage(out msg, new IntPtr(0), 0, 0, PM_NOREMOVE);

    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, new IntPtr(0), 0);

    while (GetMessage(out msg, new IntPtr(0), 0, 0))
    {
        DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
        if (abortThreadFlag)
            break;

    }
    UnhookWindowsHookEx(hhook);
}

以这种方式调用SetWindowsHook,但是id不会强制在另一个线程中调用该方法:

 Thread th = new Thread(SetWindowsHook);
 th.Start()

1 个答案:

答案 0 :(得分:2)

消息循环的目的是让Windows有机会调用您的钩子过程。没有其他方法可以调用您的代码。它无法入侵并迫使您的线程运行代码,这将导致可怕的重入问题。钩子过程只能在代码调用GetMessage()时运行。并将在该线程的上下文中运行。您可以通过查看GetCurrentThreadId()的返回值来验证这一点。

使用线程无法解决慢速挂钩过程。在挂钩过程返回之前,Windows不会调度任何其他输入事件。使它足够慢,Windows将强行杀死钩子恢复。考虑使用从线程安全队列中提供的工作线程,允许挂钩过程快速返回。