У меня есть класс, который содержит несколько делегатов, давайте назовем его EventContainer
. Этот класс передается в собственную C ++ dll, где делегаты регистрируются как обратные вызовы для различных событий.
public class EventContainer
{
public readonly SomeDelegate OnEvent1;
// ...
}
Другой класс переносит эти делегаты в соответствующие C# события.
public class EventWrapper : IDisposable
{
public event EventHandler Event1;
private GCHandle _gcHandle;
public EventWrapper()
{
var container = new EventContainer(OnEvent1)
_gcHandle = GCHandle.Alloc(container); // gets freed in Dispose
UnmanagedApi.RegisterEvents(container); // register the delegates (also unregistered in Dispose)
}
private void OnEvent1()
{
Event1?.Invoke(this, EventArgs.Empty);
}
//...
}
Контейнер должен быть закреплен, потому что управление памятью. net иногда перемещает объекты в куче, и указатели на функции на стороне C ++ могут зависнуть, если это произойдет. Поэтому я хочу проверить, правильно ли прикреплен (и освобожден) контейнер (или, точнее, делегаты внутри него). Тестирование выпущено часть проста, но тестирование правильно закреплено часть сложно.
Мне бы пришлось заставить G C (или того, кто отвечает за сжатие кучи) переместить контейнер в кучу, чтобы делегаты получили новый адрес памяти. Если контейнер закреплен, его нельзя перемещать, и поэтому вызовы событий на стороне C ++ будут работать. Однако, если контейнер не был закреплен, указатели функций на стороне C ++ будут зависать, и их вызов после перемещения контейнера вызовет AccessViolationException
(что-то в этом духе).
Для проверки это, я должен заставить переместить контейнера в кучу. Это возможно?