2010-08-08 21 views
115

Quiero saber acerca de los recursos no administrados. ¿Alguien puede darme una idea básica?¿Qué son exactamente los recursos no administrados?

+0

Consulte también esta página, que brinda una explicación fantástica y un patrón para el uso correcto de IDisposable, y cómo tomar en cuenta los recursos no administrados: http://stackoverflow.com/questions/538060/proper-use-of-the -disponible-interfaz –

Respuesta

133

Los recursos administrados básicamente significan "memoria administrada" que es administrada por el recolector de basura. Cuando ya no tenga ninguna referencia a un objeto administrado (que usa memoria administrada), el recolector de basura (eventualmente) lanzará esa memoria por usted.

Los recursos no administrados son entonces todo lo que el recolector de basura no conoce. Por ejemplo:

  • Abrir archivos
  • abrir conexiones de red
  • memoria no administrada
  • En XNA: tampones de vértices, tampones índice, texturas, etc.

Normalmente desea liberar los recursos no administrados antes de pierde todas las referencias que tiene al objeto que los gestiona. Para ello, llame al Dispose en ese objeto, o (en C#) usando la instrucción using que se encargará de llamar al Dispose por usted.

Si descuida al Dispose de sus recursos no administrados correctamente, el recolector de basura finalmente lo manejará cuando el objeto que contiene ese recurso sea basura (esto es "finalización"). Pero debido a que el recolector de basura no sabe acerca de los recursos no administrados, no puede decir cuánto necesita liberarlos, por lo que es posible que su programa funcione mal o se quede sin recursos por completo.

Si implementa una clase usted mismo que maneja recursos no administrados, le corresponde a usted implementar Dispose y Finalize correctamente.

+3

conexión de base de datos abierta viene bajo qué categoría? Managed/Unmanaged? –

+6

+1 Otras respuestas omiten el punto importante al que llamas Disposición en un objeto * managed * que gestiona internamente la liberación del recurso no administrado que envuelve (por ejemplo, identificador de archivo, GDI + mapa de bits, ...) y que si accedes sin gestionar recursos directamente (PInvoke, etc.) debe manejar eso. –

+2

@Dev: no administrado, ya que el GC no lo sabe (suponiendo que no esté usando alguna base de datos de memoria administrada hipotética). Pero el objeto de conexión * en sí mismo podría no contener un recurso no administrado. Presumiblemente, la conexión de la base de datos utiliza un archivo abierto o conexión de red * en algún lugar *, pero es * posible * que otro objeto (que no sea el objeto de conexión) maneje ese recurso no administrado (tal vez su biblioteca de base de datos almacena conexiones en caché). Verifique la documentación y vea dónde le pide que llame a 'Dispose' o use' using'. –

4

La diferencia básica entre un administrado y recurso no administrado es que el colector basura sepa acerca de todos los recursos gestionados, en algún momento en el tiempo la GC va a llegar y limpiar toda la memoria y los recursos asociados con un objeto administrado . El GC no conoce los recursos no administrados, como como archivos, transmisión y manejadores, por lo que si no los limpia de forma explícita en el código , terminará con pérdidas de memoria y recursos bloqueados.

Robado de here, no dudes en leer la publicación completa.

9

Los recursos no administrados son aquellos que se ejecutan fuera del tiempo de ejecución de .NET (CLR) (también conocido como código no .NET). Por ejemplo, una llamada a una DLL en la API de Win32 o una llamada a un archivo .dll escrito en C++ .

3

Un "recurso no administrado" no es una cosa, sino una responsabilidad. Si un objeto posee un recurso no administrado, eso significa que (1) alguna entidad externa ha sido manipulada de una manera que puede causar problemas si no se limpia, y (2) el objeto tiene la información necesaria para realizar dicha limpieza y es responsable para hacerlo

Aunque muchos tipos de recursos no administrados están muy fuertemente asociados con varios tipos de entidades del sistema operativo (archivos, identificadores GDI, bloques de memoria asignados, etc.) no hay un solo tipo de entidad compartida por todos ellos que la responsabilidad de la limpieza.Por lo general, si un objeto tiene la responsabilidad de realizar la limpieza, tendrá un método de eliminación que le ordena llevar a cabo toda la limpieza de la que es responsable.

En algunos casos, los objetos tendrán en cuenta la posibilidad de que puedan ser abandonados sin que nadie haya llamado primero Dispose. El GC permite que los objetos soliciten la notificación de que han sido abandonados (llamando a una rutina llamada Finalizar), y los objetos pueden usar esta notificación para realizar la limpieza ellos mismos.

Términos como "recurso administrado" y "recurso no administrado" son, desafortunadamente, utilizados por diferentes personas para significar cosas diferentes; francamente, creo que es más útil pensar en términos de objetos como no tener ninguna responsabilidad de limpieza, tener una responsabilidad de limpieza que solo se atenderá si se llama a Dispose o tener una responsabilidad de limpieza que se debe cuidar mediante Dispose, pero que puede también ser atendido por Finalize.

1

Cualquier recurso para el que se asigna memoria en el montón administrado .NET es un recurso administrado. CLR es completamente consciente de este tipo de memoria y hará todo lo posible para asegurarse de que no quede huérfana. Cualquier otra cosa no está administrada. Por ejemplo, interoperar con COM, podría crear objetos en el espacio de la memoria proces, pero CLR no se encargaría de ello. En este caso, el objeto gestionado que realiza llamadas a través de la delimitación gestionada debe ser el responsable de todo lo que esté más allá.

31

Algunos usuarios clasifican los archivos abiertos, las conexiones de base de datos, la memoria asignada, los mapas de bits, las secuencias de archivos, etc. entre los recursos gestionados, entre otros, los no administrados. Entonces, ¿se administran o no?

Mi opinión es que la respuesta es más compleja: cuando abre un archivo en .NET, probablemente use alguna clase .NET incorporada System.IO.File, FileStream u otra cosa. Debido a que es una clase .NET normal, se administra. Pero es un contenedor, que dentro hace el "trabajo sucio" (se comunica con el sistema operativo usando Win32 dlls, llamando a funciones de bajo nivel o incluso instrucciones de ensamblador) que realmente abre el archivo. Y esto es, lo que .NET no conoce, no administrado. Pero quizás pueda abrir el archivo usted mismo usando las instrucciones del ensamblador y eludir las funciones del archivo .NET. Entonces, el identificador y el archivo abierto son recursos no administrados.

Lo mismo con la base de datos: si utiliza algún conjunto de base de datos, tiene clases como DbConnection, etc., que son conocidas por .NET y administradas. Pero envuelven el "trabajo sucio", que no está administrado (asigna memoria en el servidor, establece conexión con él, ...). Si no utiliza esta clase de contenedor y abre un socket de red usted mismo y se comunica con su propia base de datos extraña utilizando algunos comandos, no se administra.

Estas clases de contenedor (File, DbConnection etc.) son administradas, pero dentro usan recursos no administrados de la misma manera que usted, si no usa los contenedores y hace el "trabajo sucio" usted mismo. Y, por lo tanto, estas envolturas implementan los patrones Dispose/Finalize. Es su responsabilidad permitir que el programador libere recursos no administrados cuando el contenedor ya no es necesario, y liberarlos cuando el contenedor es basura. El recopilador de basura recogerá correctamente el contenedor, pero los recursos no administrados que se encuentran en el interior se recopilarán utilizando el patrón Dispose/Finalize.

Si no utiliza las clases .NET incorporadas o de terceros y abre archivos mediante algunas instrucciones de ensamblador, etc. en su clase, estos archivos abiertos no se administran y usted DEBE implementar el patrón de eliminación/finalización. Si no lo hace, habrá una pérdida de memoria, recurso bloqueado para siempre, etc. incluso cuando ya no lo use (operación de archivo completa) o incluso después de que finalice la aplicación.

Pero su responsabilidad es también al usar estos envoltorios.Para aquellos que implementan dispose/finalize (los reconoce, que implementan IDisposable), implemente también su patrón de eliminación/finalización y deseche incluso estos wrappers o déles la señal para liberar sus recursos no administrados. Si no lo hace, los recursos estarán disponibles después de un tiempo indefinido, pero está limpio liberarlo inmediatamente (cierre el archivo inmediatamente y no lo deje abierto y bloqueado aleatoriamente por varios minutos/horas). Entonces, en el método Dispose de su clase, llama a Dispose methods de todos sus wrappers usados.

+0

Bueno uno en la claridad adicional sobre 'recursos administrados vs no gestionados' –

+0

thx para su respuesta. ¿Qué clases se recomienda que llamemos a Dispose on? – BKSpurgeon

+0

Esto es simple. En cada clase que use, debe verificar si implementa una interfaz IDisposable. En caso afirmativo, si utiliza dicha clase en un método (por ejemplo, abrir un archivo, almacenar texto, cerrar el archivo), puede usarlo usando el patrón() {}, que llama Eliminar para usted automáticamente. Si utiliza dicha clase en más métodos (por ejemplo: su clase contiene Archivo, en el constructor abre el archivo, luego varios métodos agregan algunos registros ...), luego debe implementar la interfaz IDisposable por su clase, implementar el patrón Dispose/Finalize y disponer adecuadamente el objeto de esa clase. – Martas

Cuestiones relacionadas