您的位置:首页 > 其它

.net CallbackOnCollectedDelegate 垃圾回收问题。 (Handle::Invoke”类型的已垃圾回收委托进行了回调。)

2012-07-26 17:22 555 查看
错误信息:

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

最近在写一段程序,一开始运行正常,但执行几次后就抛出错误信息。。插了MSDN,

解决办法是把委托赋值给类的成员;

例如:

原来的委托:

public delegate int HookProc(int Code, Int32 wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

调用SetWindowsHookEx:

SetWindowsHookEx(13,New HookProc(xxx) , Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

运行几次后就会出现错误,HookProc被回收了,

解决办法:

public class test

{

..........

private static HookProc hookproc;

..........

hookproc=new HookProc(xxx);

SetWindowsHookEx(13,hookproc , Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

}

这样就不会抛出异常。。。

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

找了半天,终于发现,我对自己的dllimport文件再次打包,成为一个类,但是这个类不是静态调用,所以使用callback的时候,类被回收了。

必须静态调用这个打包类。

之前把delegate变成一个方法的内部变量,结果一录像就:

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

后来作为了外部域录像录制了10多秒,就提示:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

估计是内存释放问题。。。

汇总以下,肯定是delegate被回收的问题。参考文献:

http://msdn.microsoft.com/zh-cn/library/43yky316(VS.80).aspx

http://topic.csdn.net/u/20080423/03/43b58852-5cac-4aac-a7da-6a69e69b21cd.html

reference:

http://msdn.microsoft.com/zh-cn/library/system.gc.keepalive.aspx

http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.languages.csharp/2006-09/msg01380.html

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d12c13a6-f103-48c8-9933-291a1685941a/

http://blog.csdn.net/fanweiwei/archive/2007/09/11/1780742.aspx

http://social.msdn.microsoft.com/Forums/en-US/clr/thread/66ea26a6-7c3d-4e96-9336-e3f148659f22/
http://topic.csdn.net/u/20080423/03/43b58852-5cac-4aac-a7da-6a69e69b21cd.html
keyword:GC, CALLBACK,DELEGATE, DLLIMPORT

问题解决了。是接口声明问题:

错误的声明:

public delegate int StreamDirectReadCallback(int channelNumber, [MarshalAs(UnmanagedType.LPArray, SizeConst = 704 * 576 * 5)] byte[] DataBuf, uint Length, Pixysoft.HikVision.DS40xxSDK.FrameType_t FrameType, System.IntPtr
context);

正确的声明:

public delegate int StreamDirectReadCallback(int channelNumber, IntPtr DataBuf, uint Length, Pixysoft.HikVision.DS40xxSDK.FrameType_t FrameType, System.IntPtr context);

你这些局域委托给垃圾回收器清理了。

写成类下的全局变量。

用一些集合对象存起来,如果单个就写单个,类下的全局委托变量指向即可。

这样就不会给垃圾回收器给清掉,当然除非你当前类对象都给清理掉。

如果不是因为给垃圾回收器自动回收的,那你要检查一下,你有没有哪些写了一些代码把该委托清理了。

NetSDK.fRealDataCallBack xx = RD;

的作用域可能有问题,可把它放在函数的外部,即类内;

我前几天调试一个程序也出现类似问题,就是因为委托的作用域大于委托实例的原因,请试下!

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

用15楼的方法可以解决问题。

先在类中定义NetSDK.fRealDataCallBack xx;

再在方法中用

xx = new NetSDK.fRealDataCallBack(RD);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐