The delegate should not be pinned. The managed entity is pinned if it cannot be moved by the garbage collector. If the sorting information is correct, the marshalling layer will provide a pointer to something fixed.
However, the above comment, in which you suggest that a local variable can hold a delegate alive, indicates a misunderstanding of the lifetime variable. I refer you to a specification that states:
The actual lifetime of a local variable is implementation dependent. For example, the compiler can statically determine that a local variable in a block is used only for a small part of this block. Using this analysis, the compiler can generate code that causes the variable store to have a shorter lifetime than its containing block. The storage referenced by the local reference variable is restored regardless of the lifetime of this local reference variable
In other words, if you say:
void M() { Foo foo = GetAFoo(); UnmanagedLibrary.DoSomethingToFoo(foo); }
then the jitter is allowed to say "you know, I see that no managed code ever used foo again after the moment the unmanaged call was called, so I can aggressively return the storage of this object from another thread at that time", This means that the unmanaged call can work above an object when it is suddenly freed from another stream.
This is especially unpleasant if Foo has a destructor. The termination code may run in another thread while the object is being used by an unmanaged library, and heaven only knows that this can lead to disaster.
In this case, you must use KeepAlive to support the managed entity. Do not rely on a local variable; local variables are specifically documented as not , guaranteed to support life.
See http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx for details.
Eric Lippert
source share