【发布时间】:2019-03-27 21:44:26
【问题描述】:
我需要在非托管代码中注册回调,但看起来 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);
【问题讨论】:
-
你试过把它放在例行程序的末尾吗?
-
@JoeSewell 还没有,但我马上试试
-
@JoeSewell 我试过了,但没有任何影响
-
您提到回调是“已处置”的-您的意思是某事在其上调用
Dispose?这与垃圾收集不同。如果回调对象在非托管代码使用它之前被释放,该对象仍然存在于内存中,但非托管代码可能无法使用该对象,具体取决于对象被释放的语义。 -
一个keepalive保持引用存活直到keepalive,所以它必须去last,并且允许root在最后一个之后立即消失活着。但是就是说,您没有提供任何证据表明您的问题是 GC 正在收集您的委托。您的症状是没有调用代表。如果它在被非托管代码调用之前就被收集了,那么您可能会使运行时崩溃。弄清楚谁应该打电话给代表以及为什么不打电话。
标签: c# garbage-collection unmanaged