0

In my C# app I want to do the keyhook but so, that the method invoked when the key is pressed is invoked in another thread. In this way it will not happen, that a key is omitted by my program, because my application was busy with something else. How can I make it in another thread? I have found information that, depending on the thread in which I create the hook, the method invoked when the key is pressed will be invoked in that thread, but that does not happen. Regardless of the thread in which I hooked it, this method is always invoked in the main thread. Please help. This is the outline of my code:

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 is invoked in this way, but id doesn't force the method to be invoked in another thread:

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

1 Answers1

4

The point of the message loop is to give Windows an opportunity to call your hook procedure. There is no other way for it to call your code. It cannot break in and force your thread to run code, that would cause horrible re-entrancy problems. The hook procedure can only run when your code calls GetMessage(). And will run in the context of that thread. You can verify this by looking at the return value of GetCurrentThreadId().

Using a thread is otherwise no fix for a slow hook procedure. Windows won't dispatch any other input events until the hook procedure returns. Make it slow enough and Windows will kill the hook forcibly to recover. Consider using a worker thread that you feed from a thread-safe queue instead, allowing your hook procedure to quickly return.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks for answer. But look, my SetWindowsHook(), SetWindowsHookEx() and the loop is invoked in my Thread 'th', which is not a main app thread. But the HookProc is called in main thread - and I have no idea why it is happening. – user1178232 Jul 07 '12 at 13:10
  • Hmm, the hook procedure will be called in context of the thread you started. Look at the return value of GetCurrentThreadId() – Hans Passant Jul 07 '12 at 13:14
  • Thread id of SetWindowsHook and HookProc is the same = 'many values', and other than MainWindowThread = '0'. So you are right. But that means I still do not undearstand one thing. If I call Thread.Sleep(5000) in HookProc, my window is bussy and I can't move it - that's why I thought the threads are the same. Why is it happening? – user1178232 Jul 07 '12 at 13:33
  • You are blocking the code inside Windows that dispatches input events. Sleep a couple of seconds more and Windows automatically kills your hook to recover. Clearly doing it this way is no solution to a slow hook. Consider a separate worker thread instead that you feed from a thread-safe queue so you can quickly return from the hook procedure. – Hans Passant Jul 07 '12 at 13:43
  • Thanks a lot for everything! Bless ya! ;) – user1178232 Jul 07 '12 at 13:50