我需要在非托管代码中注册一个回调,但是看起来GC一直在收集我的引用。因此,我添加了GC.KeepAlive(callback_pin);
,但没有任何效果。我不确定应该将GC.KeepAlive
放在哪里。
这是我将自己的回调注册到非托管事件的代码,它是从线程中调用的。 (Some_Callback和Some_Method是外部对象)
var callback_pin = new Some_Callback(MyManagedCallback);
GC.KeepAlive(callback_pin);
Some_Method(callback_pin);
return true;
以下是我导入非托管代码的方式。随附的文档建议我使用上述代码来使回调保持活动状态,但是由于在我的案例中从未触发过该回调,因此我认为这不是正确的方法。有什么启示吗?
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public delegate void Some_Callback(Int32 line, [MarshalAs(UnmanagedType.LPWStr)] string msg);
[DllImport("SOME_DLL.dll", CharSet = CharSet.Unicode)]
public static extern Int32 Some_Method(MulticastDelegate funcPtr, Int32 mask);
答案 0 :(得分:2)
在代表他们作为参数参与的本机功能期间,代表会自动“存活”(技术术语为“ rooted”)。
如果要调用的本机函数仅存储指针,则只需要特殊的代码即可使它们保持活动状态,然后在以后某个时刻,另一个函数(或线程)使用存储的指针。可以想象到那时,该框架可以垃圾回收您的委托。
此外,您的问题有所不同,如果委托被垃圾回收,则在调用它时会遇到访问冲突。如果什么也没发生,那么您的本机函数就是不调用它-调试它!