试图让代表继续活着

时间:2015-04-02 12:27:31

标签: c#

首先,我完全是100%对任何类型的编程都是新的,所以我很抱歉这是一个非常明显的错误,但我找不到任何东西。

我正在尝试在我的程序中实现一个全局热键,我需要让这个委托保持活动以防止CallbackOnCollectedDelegate错误,但是我的代码给了我以下两个构建错误:

  

无效的令牌'('在类,结构或接口成员声明中

     

类,结构或接口成员声明中的无效标记')'

    public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
    GC.KeepAlive(keyboardHookProc);

    public struct keyboardHookStruct {
        public int vkCode;
        public int scanCode;
        public int flags;
        public int time;
        public int dwExtraInfo;
    }

    const int WH_KEYBOARD_LL = 13;
    const int WM_KEYDOWN = 0x100;
    const int WM_KEYUP = 0x101;
    const int WM_SYSKEYDOWN = 0x104;
    const int WM_SYSKEYUP = 0x105;

感谢任何帮助,谢谢!

1 个答案:

答案 0 :(得分:0)

您无法使代理声明保持活动状态。另外,请勿将GC.KeepAlive()用于此目的;虽然它适用于“托管引用非托管代码”场景,但只有在同一方法中设置和清除钩子时才有用(有关更多信息,请参阅this link)。

这些钩子的问题是非托管代码具有您的委托的地址,但该引用位于垃圾收集器的雷达之下。因此,一段时间后垃圾收集器开始清理,非托管代码调用现在无效的地址。

如果您的应用程序在其整个生命周期内保持键盘连接,一个简单的解决方案是将其分配给静态成员:

static keyboardHookProc myKeyboardDelegate;

void SetHook()
{
    myKeyboardDelegate = new keyboardHookProc(MyHandler);
    UnmanagedMethod(myKeyboardDelegate);
}

int MyHandler(int code, int wParam, ref keyboardHookStruct lParam)
{
    ...
}

但是有更好的方法,你可以将它包装在一个类中,并将代理隐藏在应用程序的其余部分中。只需确保保留对您提供给非托管代码的委托的引用,直到删除钩子为止。