首先,我完全是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;
感谢任何帮助,谢谢!
答案 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)
{
...
}
但是有更好的方法,你可以将它包装在一个类中,并将代理隐藏在应用程序的其余部分中。只需确保保留对您提供给非托管代码的委托的引用,直到删除钩子为止。