Я думаю, что произойдет что-то не так (но не всегда), когда вы просто сохраните объект делегата.Как мы все знаем, управляемая память будет организована сборщиком мусора.(Это означает, что адрес физической памяти управляемого объекта будет изменен.)
Представление о том, что существует долговременный делегат, который будет вызываться собственным кодом, мы устанавливаем делегат как статический член или член класса,Но иногда (мы не знаем, когда, мы просто знаем, что это произойдет), GC упорядочил память, и физическая память делегата может быть от 0x000000A до 0x0000010.Но нативный код ничего не знает об этом, а нативный код знает, что он всегда звонит по адресу 0x000000A.Таким образом, мы должны не только хранить объект делегата, но также использовать GCHandle.Alloc, чтобы сказать GC не перемещать физическую память объекта делегата.Тогда нативный код преуспеет во время обратного вызова.
Хорошо, поскольку GC не организует управляемую память часто, поэтому для делегата с коротким сроком службы даже вы не вызываете GCHandle.Alloc , yourкоды всегда "DO WELL" , но иногда это будет безумием.Теперь вы знаете причину.
ссылка: http://dotnet.dzone.com/news/net-memory-control-use-gchandl