Where do I put GC.KeepAlive?

2019-08-24 22:31发布

问题:

I need to register a callback in unmanaged code, but it looks like GC keeps collecting my reference. So I added GC.KeepAlive(callback_pin); but it has no effect. I'm not sure where should I put GC.KeepAlive.

This is the code where I register my own callback to the unmanaged event, it is called from a thread. (Some_Callback and Some_Method are external objects)

var callback_pin = new Some_Callback(MyManagedCallback);
GC.KeepAlive(callback_pin);
Some_Method(callback_pin);
return true;

And below is how I imported the unmanaged code. The documentation which came with it suggests that I use the above-mentioned code in order to keep the callback alive, but since the callback is never fired in my case I don't think it's the right way to do it. Any enlightenments?

[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:

Delegates are automatically "kept alive" (the technical term is "rooted") for the duration of native functions in which they participate as parameters.

You only need special code to keep them alive if the native function you're calling is only storing the pointer, then at some later point another function (or thread) uses the stored pointer. The framework could conceivably garbage collect your delegate by then.

Besides, your issue is different, if the delegate was garbage collected you'd be getting an access violation when calling it. If nothing is happening, your native function simply isn't calling it -- debug it!