В чем разница между HandleRef и GCHandle? - PullRequest

Ответы [ 2 ]

7 голосов
/ 19 декабря 2011

Смысл обеих этих структур состоит в том, чтобы не дать сборщику мусора освободить ресурс и сделать недействительным дескриптор до завершения вызова P / Invoke. Связанная с вами документация указывает, что это специальные типы, распознаваемые маршаллером взаимодействия.

Из документации я понял, что HandleRef по сути является частным случаем более общей структуры GCHandle.

Структура HandleRef специально предназначена для переноса дескрипторов на неуправляемые ресурсы, которые используются с кодом P / Invoke. Например, дескрипторы окон (HWND) или контексты устройства (HDC). Он имеет свойство Handle, которое возвращает значение типа IntPtr, которое является целочисленным значением размера указателя на архитектуру базовой системы. Вы можете использовать это, чтобы быстро и легко получить ручку, которую оборачивает.

Принимая во внимание, что структура GCHandle позволяет указать тип дескриптора, который она переносит, используя один из элементов перечисления GCHandleType, структура HandleRef была специально разработана для переноса дескрипторов на неуправляемые ресурсы. Вы, вероятно, будете использовать структуру GCHandle, когда имеете дело непосредственно с неуправляемой памятью, а не со специальными дескрипторами, которые Win32 API рассматривает как черные ящики.

Нет необходимости использовать либо. Можно просто позвонить GC.KeepAlive, чтобы не дать сборщику мусора преждевременно освободить ресурс.

И даже это, вероятно, не нужно. Я годами писал код P / Invoke и обнаружил, что когда он написан правильно, нет необходимости ни в одной из этих структур. Если объект класса получает мусор во время выполнения вызова API, это ошибка в вашем приложении. Я на самом деле хочу, чтобы уведомлялся о сбое через исключение, а не скрывал его.

0 голосов
/ 19 декабря 2011

Одна разница указана в ссылке , которую вы упомянули:

Тип значения HandleRef, такой как GCHandle, является специальным распознаваемым типом. по взаимодействию маршалер. Нормальный, не закрепленный GCHandle также предотвращает несвоевременная сборка мусора, но HandleRef обеспечивает лучшее спектакль. Хотя с помощью HandleRef, чтобы сохранить объект для Продолжительность вызова вызова платформы является предпочтительным, вы также можете использовать Метод GC.KeepAlive для той же цели.

...