I need to pass a managed callback to an unmanaged TCP receiver. Since its a thread that needs to exist for the lifetime of the application, I need to prevent it from getting garbage collected. I have read everywhere that pinning function pointers is not required and the GCHandle.Alloc will do the job of preventing garbage collection.
But is this a given? I have seen that the AppPool hosting this code crashes with an access violation. Why should I not suspect the fact that this error occurs because the function pointer was garbage collected?
This post supports this fact.
Update: This seems to have reduced the crashes considerably. Is there a problem with this approach?
typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize);
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler);
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp;
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer);
I do exactly what you suggest to do - GCHandle.Alloc on the delegate but with no pinning - and have not had any problems in extensive use on many different platforms and on .NET versions 2.0 - 4. Something like:
DelegateHandle = GCHandle.Alloc(xlDelegate);
FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate);
with FunctionPointer
then passed to the native code, and DelegateHandle
kept for later cleanup.
This seems to be the best reference: http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx.
Nothing in the post you point to contradicts this reference - you do need to protect the delegate from garbage collection, it's just that pinning is not required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With