Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 错误:CallbackOnCollectedDelegate-如何找到确切的已收集项目?_C#_Exception_Garbage Collection_Delegation - Fatal编程技术网

C# 错误:CallbackOnCollectedDelegate-如何找到确切的已收集项目?

C# 错误:CallbackOnCollectedDelegate-如何找到确切的已收集项目?,c#,exception,garbage-collection,delegation,C#,Exception,Garbage Collection,Delegation,成功运行几分钟后,我的应用程序中出现此错误 对类型为的垃圾回收委托进行了回调 “我的应用程序!myApp.globalKeyboardHook+keyboardHookProc::Invoke' 我知道这是因为垃圾收集器杀死了一个对象或其他东西,而我的代码仍在引用相同的东西 如果是这种情况,GC更可能收集哪个对象或组件。我怎样才能克服这个错误。(有参考号??) 因为我不能确定代码的哪一部分是导致这个问题的原因,所以我在这里发布了完整的类。(我想这对我的其他课程没有问题) 类globalKeybo

成功运行几分钟后,我的应用程序中出现此错误

对类型为的垃圾回收委托进行了回调 “我的应用程序!myApp.globalKeyboardHook+keyboardHookProc::Invoke'

我知道这是因为垃圾收集器杀死了一个对象或其他东西,而我的代码仍在引用相同的东西

如果是这种情况,GC更可能收集哪个对象或组件。我怎样才能克服这个错误。(有参考号??)

因为我不能确定代码的哪一部分是导致这个问题的原因,所以我在这里发布了完整的类。(我想这对我的其他课程没有问题)

类globalKeyboardHook
{
公共委托int keyboardHookProc(int代码、int wParam、ref keyboardHookStruct lParam);
公共结构keyboardHookStruct
{
公共int-vkCode;
公共int扫描码;
公共国旗;
公共整数时间;
公共信息;
}
IntPtr hInstance;
const int WH_键盘LL=13;
常量int WM_KEYDOWN=0x100;
常量int WM_SYSKEYDOWN=0x104;
public List HookedKeys=新列表();
IntPtr hhook=IntPtr.Zero;
//事件
公共事件KeyEventHandler KeyDown;
公共globalKeyboardHook()
{
钩子();
}
~globalKeyboardHook()
{
解开钩();
}
公共空钩()
{
hInstance=LoadLibrary(“User32”);
hhook=SetWindowsHookEx(WH_-KEYBOARD,hookProc,hInstance,0);
}
公共空间取消挂钩()
{
脱钩(hhook);
}
public int hookProc(int代码、int wParam、ref keyboardHookStruct lParam)
{
如果(代码>=0)
{
Keys key=(Keys)lParam.vkCode;
如果(1==1)
{
KeyEventArgs kea=新的KeyEventArgs(key);
if((wParam==WM|u KEYDOWN | wParam==WM_SYSKEYDOWN)&&(KEYDOWN!=null))
{
KeyDown(这个,kea);
}
如果(千欧处理)
返回1;
}
}
返回CallNextHookEx(hhook、code、wParam、ref lParam);
}
//DLL导入
[DllImport(“user32.dll”)]
静态外部IntPtr SETWINDOWSHOOKX(int idHook、keyboardHookProc回调、IntPtr hInstance、uint threadId);
[DllImport(“user32.dll”)]
静态外部bool unhookwindowshookx(IntPtr hInstance);
[DllImport(“user32.dll”)]
静态extern int CallNextHookEx(IntPtr idHook、intncode、intwparam、ref keyboardHookStruct lParam);
[DllImport(“kernel32.dll”)]
静态外部IntPtr加载库(字符串lpFileName);
}
}
您肯定很难找到收集的项目,因为它在您的程序中不可见。这里的C#语言有点太友好了。您依靠其语法自动为
hookProc
创建委托对象。此代码编译为:

    keyboardHookProc $unspeakable = new keyboardHookProc(hookProc);
    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, $unspeakable, hInstance, 0);
这在pinvoke中是一个问题,垃圾收集器不知道$unspeakable委托对象实际上正被本机代码使用。它只能看到对对象的托管引用。因此,一旦发生gen#0垃圾回收,它就会收集对象。当Windows进行钩子回调时发出“咔咔”声

由您来确保无法收集此委托对象。使用GCHandle.Alloc()。或者简单的方法,将其显式存储在变量中。这很好,因为您让终结器销毁了钩子:

    IntPtr hhook = IntPtr.Zero;
    keyboardHookProc callback;

    public void hook()
    {
        if (callback != null) throw new InvalidOperationException("Hook already installed");
        if (hInstance == IntPtr.Zero) hInstance = LoadLibrary("User32");
        callback = new keyboardHookProc(hookProc);
        hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callback, hInstance, 0);
    }

    public void unhook()
    {
        UnhookWindowsHookEx(hhook);
        callback = null;
    }
您肯定很难找到收集的项目,因为它在您的程序中不可见。这里的C#语言有点太友好了。您依靠其语法自动为
hookProc
创建委托对象。此代码编译为:

    keyboardHookProc $unspeakable = new keyboardHookProc(hookProc);
    hhook = SetWindowsHookEx(WH_KEYBOARD_LL, $unspeakable, hInstance, 0);
这在pinvoke中是一个问题,垃圾收集器不知道$unspeakable委托对象实际上正被本机代码使用。它只能看到对对象的托管引用。因此,一旦发生gen#0垃圾回收,它就会收集对象。当Windows进行钩子回调时发出“咔咔”声

由您来确保无法收集此委托对象。使用GCHandle.Alloc()。或者简单的方法,将其显式存储在变量中。这很好,因为您让终结器销毁了钩子:

    IntPtr hhook = IntPtr.Zero;
    keyboardHookProc callback;

    public void hook()
    {
        if (callback != null) throw new InvalidOperationException("Hook already installed");
        if (hInstance == IntPtr.Zero) hInstance = LoadLibrary("User32");
        callback = new keyboardHookProc(hookProc);
        hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callback, hInstance, 0);
    }

    public void unhook()
    {
        UnhookWindowsHookEx(hhook);
        callback = null;
    }