类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法

Posted 微笑着写代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法相关的知识,希望对你有一定的参考价值。

《对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们》的问题的解决方法

源程序部分代码如下

[csharp] view plain copy
 
  1. /// <summary>  
  2. /// 安装钩子的函数  
  3. /// </summary>  
  4. /// <param name="idHook"></param>  
  5. /// <param name="lpfn"></param>  
  6. /// <param name="hInstance"></param>  
  7. /// <param name="threadId"></param>  
  8. /// <returns></returns>  
  9. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  10. public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);  
  11. /// <summary>  
  12. /// 卸下钩子的函数  
  13. /// </summary>  
  14. /// <param name="idHook"></param>  
  15. /// <returns></returns>  
  16. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  17. public static extern bool UnhookWindowsHookEx(int idHook);  
  18. /// <summary>  
  19. /// 下一个钩挂的函数  
  20. /// </summary>  
  21. /// <param name="idHook"></param>  
  22. /// <param name="nCode"></param>  
  23. /// <param name="wParam"></param>  
  24. /// <param name="lParam"></param>  
  25. /// <returns></returns>  
  26. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  
  27. public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);  
  28.   
  29. //定义了一个委托  
  30. public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);  
  31.   
  32.   
  33. //定义一个代理  
  34. HookProc KeyboardHookDelegate;  
  35.   
  36.   
  37. /// <summary>  
  38. /// 创建钩子  
  39. /// </summary>  
  40. public void SetHook()  
  41. {  
  42.     KeyboardHookDelegate = new HookProc(KeyboardHookProc);  
  43.     Process cProcess = Process.GetCurrentProcess();  
  44.     ProcessModule cModule = cProcess.MainModule;  
  45.     var mh = GetModuleHandle(cModule.ModuleName);  
  46.     hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);  
  47. }  
  48.   
  49.   
  50. public void UnHook()  
  51. {  
  52.     UnhookWindowsHookEx(hHook);  
  53. }  
  54.   
  55.   
  56. /// <summary>  
  57. /// 键盘钩子进程  
  58. /// </summary>  
  59. /// <param name="nCode"></param>  
  60. /// <param name="wParam"></param>  
  61. /// <param name="lParam"></param>  
  62. /// <returns></returns>  
  63. private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)  
  64. {  
  65. //...  
  66. //每到这里就报错  
  67. return CallNextHookEx(hHook, nCode, wParam, lParam);  
  68. }  


经过一番搜索,
可能的原因是定义的委托给垃圾回收机制给回收了,这导致报告如题错误,网上很多朋友们说,将委托定义为成员变量,可是我的就是成员变量还是出错,还有的说要定义代理,可我使用的就是代理了,还有的朋友们说要定义为静态的,但是似乎在我这里全部都无济于事,与似乎我我分析了一下,
终于解决了,修改如下

[csharp] view plain copy
 
  1. public void SetHook()  
  2. {  
  3.     KeyboardHookDelegate = new HookProc(KeyboardHookProc);  
  4.     IntPtr intPtr = Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]);  
  5.     hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookDelegate, intPtr, 0);  
  6. }  



原来是获得当前进程,然后获取当前进程的MainModule,再获取MainModule的ModuleName
最后用反射获取到当前程序集,如果程序没有关闭程序集一直是存在的,然后就解决了。
也许我上述理解可能有误,如果理解有误,还望大神斧正。

以上是关于类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法的主要内容,如果未能解决你的问题,请参考以下文章

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段

JVM垃圾回收概念

有垃圾回收机制为啥会出现内存溢出

Java的垃圾回收总结

-- 垃圾回收机制

Java会造成内存泄漏,多态,垃圾回收,clone