Call has been made on garbage collected delegate in C#?

后端 未结 4 930
抹茶落季
抹茶落季 2020-12-01 20:58

I have been using this key hook script i found but I continue to get an error after a few seconds of using it in my program. The error says.. A call has been made on a gar

相关标签:
4条回答
  • 2020-12-01 21:21

    The problem is that:

    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
    

    is just syntactic sugar for:

    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, new keyboardHookProc(hookProc), hInstance, 0);
    

    and so the keyboardHookProc object is just local and will get disposed of since SetWindowsHookEx doesn't do anything to actually hold onto it in the managed world.

    To fix this, up at the top where you define your member variables, add one more like this:

    IntPtr hhook = IntPtr.Zero
    private keyboardHookProc hookProcDelegate;
    

    then change your constructor to be:

    public globalKeyboardHook()
    {
        hookProcDelegate = hookProc;
        hook();
    }
    

    and then change your hook() method to be:

    public void hook()
    {
        IntPtr hInstance = LoadLibrary("User32");
        hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProcDelegate, hInstance, 0);
    }
    

    That way you're using a delegate that is stored as a member variable and will be alive as long as your globalKeyboardHook object is alive.

    0 讨论(0)
  • 2020-12-01 21:29

    Sounds to me like you are instantiating a globalKeyboardHook then letting it get garbage collected. I'm guessing you do something like this:

    public void InstallHook()
    {
        var hook = new globalKeyboardHook();
    }
    

    You need to keep a reference to the globalKeyboardHook() around to prevent it from being garbage collected.

    globalKeyboardHook hook;
    
    public void InstallHook()
    {
        hook = new globalKeyboardHook();
    }
    
    0 讨论(0)
  • 2020-12-01 21:31

    I'd like to add this, for future reference, as it may help understanding Tim's answer, and maybe debugging what's going on, if you have complex code:

    callbackOnCollectedDelegate MDA

    https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/callbackoncollecteddelegate-mda

    0 讨论(0)
  • even though with the new code I am still getting the mentioned error, as a solution I just kept an instance of the delegate at class scope, now the error does not come up anymore.

    //do not forget to declare kbhproc class var   
    this.kbhProc = new keyboardHookProc(hookProc);
    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, this.kbhProc /*new keyboardHookProc(hookProc)*/, hInstance, 0);
    

    the above code is based on the code of the question.

    0 讨论(0)
提交回复
热议问题