我在哪里放置GC.KeepAlive?

时间:2018-10-23 15:24:22

标签: c# garbage-collection unmanaged

我需要在非托管代码中注册一个回调,但是看起来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);

1 个答案:

答案 0 :(得分:2)

在代表他们作为参数参与的本机功能期间,代表会自动“存活”(技术术语为“ rooted”)。

如果要调用的本机函数仅存储指针,则只需要特殊的代码即可使它们保持活动状态,然后在以后某个时刻,另一个函数(或线程)使用存储的指针。可以想象到那时,该框架可以垃圾回收您的委托。

此外,您的问题有所不同,如果委托被垃圾回收,则在调用它时会遇到访问冲突。如果什么也没发生,那么您的本机函数就是不调用它-调试它!