practice net example ejemplo best asp c# .net resources idisposable

c# - net - protected override void dispose



Determinar los recursos administrados frente a los no administrados (3)

Hay muchas preguntas sobre recursos administrados y no administrados. Entiendo la definición básica de los dos. Sin embargo, me cuesta mucho saber cuándo se administra o no un recurso u objeto.

Cuando pienso en recursos no administrados, tiendo a pensar en un código nativo que no forma parte directamente de .NET, como los recursos pinvoke o de cálculo de referencias. Normalmente pensaría en recursos destinados a interactuar con algo que usará HW, como un identificador de archivo o una conexión de red que no esté administrada.

¿Qué pasa con los objetos .NET que envuelven recursos no administrados nativos, como FileStream ?

Un FileStream debe usar recursos no administrados, pero cuando implemento el patrón IDisposable , ¿debería considerar esto como un recurso administrado o no administrado?

He estado asumiendo hasta ahora que si el objeto implementa IDisposable , entonces es administrado. ¿Cómo puedo saber que IntPtr debe manejarse como un recurso no administrado?


Un FileStream debe usar recursos no administrados, pero cuando implemento el patrón IDisposable, ¿debería considerar esto como un recurso administrado o no administrado?

Un FileStream es un recurso gestionado .

Los recursos administrados son clases que contienen (y deben administrar) recursos no administrados. Por lo general, el recurso real es varias capas hacia abajo.

He estado asumiendo hasta ahora que si el objeto implementa IDisposable , entonces es administrado.

Correcto.

¿Cómo puedo saber que IntPtr debe manejarse como un recurso no administrado?

De la documentación de la API de la que obtuvo su valor. Pero tenga en cuenta que en la práctica, la mayoría de los programadores nunca tratan directamente con recursos no administrados. Y cuando tenga que hacerlo, use la clase SafeHandle para convertir un recurso no administrado en un recurso administrado.


Es bastante sencillo, nunca puede asignar accidentalmente un recurso no administrado. Se requiere una llamada de Pinvoke para asignarla, usted lo sabría. El término "objeto" está sobrecargado, pero no existe un objeto no administrado, todos los objetos en un programa .NET están administrados. Puede interoperar con código escrito en otro lenguaje que admita la creación de objetos, como C ++. Pero no puede usar directamente un objeto de este tipo, se requiere un contenedor C ++ / CLI. Lo que la convierte en una clase administrada que implementa IDisposable.

Si trabaja con una biblioteca mal documentada, entonces preste atención cuando obtenga un IntPtr de vuelta. Esa es una indicación bastante clara de que se trata de una asignación no administrada, ya sea un puntero a la memoria no administrada o un identificador del sistema operativo. Esa biblioteca también debería proporcionarle una forma de liberarla, si no lo administra automáticamente. Póngase en contacto con el propietario de la biblioteca si no está seguro de cómo manejarlo adecuadamente.

El trabajo de Microsoft era proporcionar clases de contenedor administradas en torno a todos los recursos comunes del sistema operativo. Como FileStream, Socket, etcétera. Esas clases casi siempre implementan IDisposable. Lo único que tiene que hacer en su código cuando almacena un objeto de clase de este tipo en su propia clase es implementar IDisposable usted mismo, solo para llamar al método Dispose () en ese objeto. O use la instrucción using si las usa como una variable local en un método.


Es muy útil pensar que un "recurso" en este contexto significa "algo que un objeto ha pedido que haga otra cosa en su nombre, hasta nuevo aviso, en detrimento de todos los demás". Un objeto constituye un "recurso administrado" si su abandono daría lugar a que el recolector de basura notifique al objeto de abandono, y el objeto, a su vez, instruya a cualquier persona que actuara en su nombre para que deje de hacerlo. Un "recurso no administrado" es un recurso que no está encapsulado dentro de un recurso administrado.

Si algún objeto Foo asigna un identificador a la memoria no administrada, le solicita al administrador de memoria que le otorgue el uso exclusivo de alguna área de la memoria, lo que hace que no esté disponible para ningún otro código que, de lo contrario, querría usarlo, hasta que Foo informe a la memoria. gestiona que la memoria ya no sea necesaria y, por lo tanto, debería estar disponible para otros fines. Lo que hace que el manejo de un recurso no administrado no sea el hecho de que se recibió a través de una API, sino el hecho de que incluso si se abandonaran todas las referencias deliberadas a él, el administrador de memoria continuaría otorgando el uso exclusivo de la memoria a un objeto que no ya lo necesita (y es probable que ya no exista).

Si bien los manejadores de API son el tipo más común de recursos no administrados, también hay muchos otros tipos. Cosas como los bloqueos y eventos del monitor existen completamente dentro del mundo de código administrado de .net, pero aún así pueden representar recursos no administrados, ya que adquirir un bloqueo y abandonarlo mientras el código lo está esperando puede dar como resultado que el código espere por siempre, y desde un corto período de tiempo. El objeto que se suscribe a un evento de un objeto de larga duración y no se puede anular su suscripción antes de que se abandone puede hacer que el objeto de larga duración continúe cargando la referencia del evento de forma indefinida (una pequeña carga si solo se abandona un suscriptor, pero una carga ilimitada si se crea y se abandona un número ilimitado de suscriptores).

Addendum Una suposición fundamental del recolector de basura es que cuando el objeto X contiene una referencia al objeto Y, es porque X está "interesado" en Y. Sin embargo, en algunas situaciones, la referencia puede mantenerse porque X quiere que Y tenga una referencia a pesar de que a Y no le "importa" de una manera u otra. Tales situaciones ocurren frecuentemente con los controladores de eventos de notificación. El objeto Y puede querer que se le notifique cada vez que algo le sucede al objeto X. Aunque X tiene que mantener una referencia a Y para poder realizar dichas notificaciones, a X en sí no le importan las notificaciones. Solo los realiza debido a la presunción de que a algún objeto enraizado podría importarle que Y los reciba.

En algunos casos, es posible usar lo que se llama un "patrón de evento débil". Desafortunadamente, aunque hay muchos patrones de eventos débiles en .net, todos ellos tienen peculiaridades y limitaciones debido a la falta de un tipo de WeakDelegate adecuado. Además, aunque los eventos débiles son útiles, no son una panacea. Supongamos, por ejemplo, que Y ha pedido al objeto X larga duración que le notifique cuando ocurre algo, la única referencia existente a Y es la que X utiliza para dicha notificación, lo único que Y hace con dicha notificación es incrementar una propiedad en algún objeto Z , y esa configuración de esa propiedad no modifica nada fuera de Z Bajo ese escenario, aunque el objeto Z será la única cosa en el universo que se "preocupa" por el objeto Y , Z no tendrá ningún tipo de referencia a Y , por lo que el recolector de basura no tendrá forma de vincular a Y '' s vida a la de Z Si una X tiene una fuerte referencia a Y , esta última se mantendrá viva incluso después de que nadie esté interesado en ella. Si X solo tiene una referencia débil, entonces Y puede ser recogida de basura incluso si Z está interesada en ella. No hay ningún mecanismo por el cual el recolector de basura pueda inferir automáticamente que Z está interesado en Y