IntPtr, SafeHandle y HandleRef – Explicado

Sin señalarme a MSDN, ¿podría alguien dar una explicación concisa y clara del propósito de cada uno de estos y cuándo usarlos? (IntPtr, SafeHandle y HandleRef)

IntPtr es simplemente una estructura simple basada en enteros que puede contener un puntero (es decir, tamaño de 32 bits en sistemas de 32 bits, tamaño de 64 bits en sistemas de 64 bits).

SafeHandle es una clase que está destinada a contener identificadores de objetos Win32; tiene un finalizador que asegura que el identificador se cierre cuando el objeto recibe GC. SafeHandle es una clase abstracta porque los diferentes identificadores de Win32 tienen diferentes formas en que deben cerrarse. Antes de la introducción de SafeHandle , IntPtr se usaba para mantener los identificadores de Win32, pero garantizar que se cerraran correctamente y no se les permitiera utilizar GC era responsabilidad del progtwigdor.

HandleRef es una forma de asegurarse de que un identificador no administrado no tenga GC cuando se encuentre en medio de una llamada de P / Invoke. Sin algo como HandleRef , si su código administrado no hace nada con el controlador después de la llamada P / Invoke, si el GC se ejecutó durante la llamada P / Invoke no se daría cuenta de que el identificador aún estaba en uso y podría GC . Me imagino (pero no estoy seguro y no lo he buscado) que SafeHandle podría usar HandleRef como parte de su gestión del identificador encapsulado.

 HWnd a = new HWnd(); B.SendMessage(a.Handle, ...); 

Suponiendo que esta es la única referencia a “a” en el progtwig, esto es equivalente a:

 HWnd a = new HWnd(); IntPtr h = a.Handle; // a is no longer needed and thus can be GC'ed B.SendMessage(h, ...); 

El problema es que cuando se elimina “a”, cerrará el mango. Si esto ocurre antes o durante la llamada a SendMessage, el identificador no será válido.

HandleRef evita que “a” sea recolectada como basura antes de que el progtwig termine con h.

Parece que SafeHandle incorpora el comportamiento KeepAlive de HandleRef: Project Roslyn SafeHandle.cs http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safehandle.cs,743afbddafaea263

 /* Problems addressed by the SafeHandle class: 1) Critical finalization - ensure we never leak OS resources in SQL. Done without running truly arbitrary & unbounded amounts of managed code. 2) Reduced graph promotion - during finalization, keep object graph small 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread ---- (HandleRef) <...> */ 

Pero no estoy seguro, parece que el comportamiento de keepalive solo se puede lograr al proporcionar valor falso al constructor que simplemente marca el objeto como no configurable, por lo que debe llamar a SafeHandle’s Dispose () para evitar la fuga de recursos en ese caso, am ¿Verdad? ¿Alguien puede explicar el código fuente, cuál es el

 private extern void InternalDispose(); private extern void InternalFinalize(); 

?