This is a question I had when I read the answer to this StackOverflow question. When exactly are GCHandles created for managed objects being passed into unmanaged code, and when are these handles freed?
An example where a GCHandle is created - alluded to in the link above but also verified with a memory profiling tool on my end - is within one of the methods called by the following overload of the System.Threading.Timer constructor:
public Timer(TimerCallback callback, object state, int dueTime, int period)
One of the pathway for method calls is the following, read from top to bottom:
System.Threading.Timers.TimerSetup
System.Threading.TimerBase.AddTimer
System.Threading.TimerBase.AddTimerNative
I can see from my memory profiler that the System.Threading.TimerBase.AddTimer method creates GCHandles, but I see no explicit call to GCHandle.Alloc in this method. Where is the GCHandle being created? Is it just an automatic thing that happens in .NET when a method leading to unmanaged code (in this case System.Threading.TimerBase.AddTimerNative) is called?