2011-12-19 9 views

Respuesta

7

El objetivo de ambas estructuras es evitar que el recolector de basura libere un recurso e invalidar el identificador antes de que la llamada P/Invoke haya finalizado. La documentación que vinculó indica que estos son tipos especiales reconocidos por el contador de interoperabilidad.

Lo que deduzco de la documentación es que HandleRef es esencialmente un caso especial de la estructura más general GCHandle.

La estructura HandleRef está específicamente diseñada para envolver controladores en recursos no administrados que se utilizan con el código P/Invoke. Por ejemplo, identificadores de ventana (HWND) o contextos de dispositivo (HDC). Tiene una propiedad Handle que devuelve un valor de tipo IntPtr, que es un valor entero del tamaño de un puntero en la arquitectura del sistema subyacente. Puede usar esto para rápidamente & obtener fácilmente el mango que envuelve.

Considerando que la estructura GCHandle permite especificar el tipo de mango que se envuelve usando uno de los miembros de la GCHandleType enumeración, la estructura HandleRef fue diseñado específicamente para envolver los mangos a los recursos no administrados. Probablemente usaría la estructura GCHandle cuando trabaje directamente con la memoria no administrada, en lugar de los identificadores especiales que la API de Win32 trata como cuadros negros.

No es necesario usar ninguno de los dos. Uno simplemente puede llamar al GC.KeepAlive para evitar que el recolector de basura libere el recurso de forma prematura.

E incluso eso probablemente no sea necesario. He estado escribiendo el código P/Invoke durante años, y he descubierto que, cuando está escrito correctamente, no hay necesidad de ninguna de estas estructuras. Si un objeto de la clase obtiene basura recolectada mientras la llamada API se encuentra en el medio de la ejecución, entonces eso es un error en su aplicación. De hecho, quiero para ser notificado de la falla a través de una excepción, no ocultarlo.

+0

Gracias por responder –

+1

"He encontrado que cuando está escrito correctamente, no hay necesidad de ninguna de estas estructuras." ¿Qué sucede si no está preocupado por evitar que el objeto se recopile porque sabe que el código administrado seguirá haciendo referencia a él, pero simplemente desea que el código no administrado acepte/mantenga/devuelva referencias administradas por algún motivo? Ejemplo de caso de uso: stackoverflow .com/questions/32105089 –

0

Una diferencia se da en la link usted ha mencionado:

El tipo de valor HandleRef, como GCHandle, es un tipo especial reconocido por el marcador de interoperabilidad. Un GCHandle normal no fijado también evita recolección de basura intempestiva, aunque HandleRef proporciona un mejor rendimiento . Aunque se usa HandleRef para mantener vivo un objeto para la duración de de una llamada de invocación de plataforma, también se puede usar el método GC.KeepAlive para el mismo propósito.

+0

Sí, veo eso, pero necesito información detallada –

+1

@user: ¿Qué información más detallada es la que quieres? –

Cuestiones relacionadas