2012-03-30 15 views
5

estoy usando el patrón descrito aquí para administrar cesiones: http://www.developerzen.com/2006/01/09/finalizableobject-developing-a-base-class-for-idisposable-objects/¿Qué se considera un "recurso no gestionado" en el patrón Desechable?

¿Qué cuenta como un "recurso no administrado?"

Éstos son algunos de los puntos confusos en mi mente:

  • En algún momento, .NET se acaba terminando llamadas de Win32, ¿verdad? Entonces, ¿no son la mayoría de los objetos .NET de alguna manera un recurso no administrado?
  • ¿Qué pasa con los objetos COM que tenemos contenedores .NET para - ¿qué se consideran?
  • ¿Qué pasa con las clases administradas que obtienen la funcionalidad únicamente de P/Invokes?
  • ¿Qué pasa con las clases de C++/CLI que usan internamente las bibliotecas nativas? En el nivel C#, las clases C++/CLI que tenían destructores ahora implementan IDisposable ... ¿qué se consideran?

que dan cuenta de que el blog post es un poco viejo. Si hay una manera más moderna de administrar la vida útil de los objetos administrados y no administrados, sugiérelo.

EDIT: El que está votando para cerrar esto, por favor proporcionar algunos detalles sobre cómo puedo mejorar la cuestión.

+0

* "Si hay una forma más nueva de abordar este problema ..." * ¿Cuál es exactamente el problema aquí? –

+0

Administrar el ciclo de vida de los objetos administrados y no administrados. Si hace esto en el orden incorrecto, puede tener interbloqueos – jglouie

+0

¿Qué hay de malo en el ejemplo dado en [la documentación] (http://msdn.microsoft.com/library/System.IDisposable.aspx)? –

Respuesta

7

entiendo la confusión. Creo que hay algunas pautas simples a seguir:

  1. Si su clase "posee" una referencia a otro objeto (es decir, el objeto creado por otro objeto, o se le dio la referencia a ese objeto con el entendimiento de que su objeto ahora "lo posee"), entonces usted es responsable de hacer cualquier limpieza necesaria (si la hay)

  2. Si ese otro objeto es un objeto .NET y no implementa la interfaz IDisposable, entonces probablemente no lo haga Necesito hacer cualquier cosa. La interfaz IDisposable es, por convención, la interfaz que utilizamos para declarar si nuestros objetos requieren o no limpieza.

  3. Si ese otro objeto es un objeto .NET e implementa la interfaz IDisposable, entonces su clase también debería implementar la interfaz IDisposable. En su método Dispose, simplemente llame al método Dispose del otro objeto.

  4. Si ese otro objeto es un recurso o un recurso no administrado, su clase debería implementar un finalizador para asegurarse de que el objeto/recurso no administrado se limpiará. Siga las pautas descritas en esa publicación de blog para saber cómo implementar eso.

A continuación se presentan algunas respuestas específicas a sus preguntas.

  • En algún momento, .NET es simplemente envolviendo llamadas de Win32, ¿verdad? Entonces, ¿no son la mayoría de los objetos .NET de alguna manera un recurso no administrado?

A pesar de que un objeto .NET puede envolver llamadas de Win32, el término "recurso no administrado" no es adecuado, ya que es un objeto .NET, por lo tanto, es por definición un "recurso administrado". El CLR maneja la asignación de memoria y la recolección de basura para esos objetos.

  • ¿Qué pasa con los objetos COM que tenemos envolturas para .NET - ¿Qué son considerados?

objetos .NET envoltura siguen siendo objetos .NET, por lo que son "recursos gestionados", pero tenga en cuenta que deben poner en práctica su propia disponer/finalizar la lógica. Básicamente, se encargan de limpiar los "recursos no administrados" para que usted no tenga que hacerlo. Si estuviera implementando su propio contenedor para un objeto COM, entonces sería responsable de implementar la lógica de disposición/finalización necesaria para limpiarlo, de modo que los consumidores de su contenedor no tengan que hacerlo.

  • ¿Qué pasa con las clases administradas que se interponen funcionalidad exclusivamente de P/Invoca?

Una clase que utiliza P/Invoke para llamar al código no administrado podría estar asignando recursos no administrados, dependiendo de lo que se está llamando a administrar.Por lo tanto, puede ser necesario implementar la lógica de disposición/finalización necesaria para limpiar esos recursos no administrados.

  • ¿Qué hay de clases de C++/CLI que utilizan internamente bibliotecas nativas?

Sí, los que también se pueden asignar los recursos no administrados de las bibliotecas nativas, por lo que también sería necesario que implementan la lógica destructor/finalizador necesario.

  • En el nivel C#, las clases C++/CLI que tenían destructores ahora implementan IDisposable ... lo que se considera?

En C++/CLI, se puede optar por declarar una clase que sea administrado (con la palabra clave ref) o no administrados (sin la palabra clave ref). Si se declara con la palabra clave ref, entonces es una clase administrada; se asignará en el montón administrado y será limpiado por el recolector de basura una vez que se salga del alcance y no haya más referencias al mismo. Si la clase se declara sin la palabra clave ref, no se administra y debe limpiarse explícitamente. En cualquier caso, la clase podría haber asignado recursos no gestionados que deben limpiarse en el destructor/finalizador.

+0

Muchas gracias por abordar las balas, esto realmente aclara los conceptos para mí. – jglouie

0

En primer pensamiento, cualquier cosa que esté fuera de .NET es recurso no administrado. Los objetos administrados son cadenas .net, matrices, tipos de valores y tipos complejos que se componen de ellos, todos ellos son administrados y su ciclo de vida es controlado automáticamente por .net. String no es una envoltura alrededor de algo, así que está completamente administrado.

La mayoría de las clases base de .net se escriben desde cero, como List, Stack, etc. Podemos simplificar diciendo que cualquier objeto y sus descendientes solo hacen referencia a datos dentro de su pila o se maneja el montón.

Cualquier otra conexión abierta/manejar a acceder a cualquier cosa fuera de la pila/pila es administrado, ya sea el archivo, tubería con nombre, red o cualquier dispositivo.

mayoría de las otras clases de BCL se optimizan pero a menos que se envuelven alrededor de usar el bloque, no van a ser eliminados de forma automática en cualquier forma en que se escriben.

1

Esto es lo que trato como "no administrado" (nótese las comillas):

  1. Cualquier cosa que implementa IDisposable. Si quiere ser eliminado ... bueno, confía en eso. No importa si es .NET "seguro" puro o si implementa un método de Disposición vacío. Para poder manejarlo con el patrón Desechable, es "no administrado".
  2. Cualquier COM RCW. Hay grandes debates sobre esto; I view each COM->NET RCW count-increase as "owned" and thus "unmanaged". En última instancia un RCW se limpiará en el destructor, pero "en última instancia" puede causar muchos problemas al tratar con el Modelo de objetos de Outlook, que es con lo que trabajo. Este enfoque requiere un enfoque coherente para tratar con objetos COM y tiempos de vida para evitar problemas "RCW separados".
  3. Cualquier [nuevo] recurso obtenido a través de una llamada P/Invoke como un BSTR: lo que asigna dicho recurso "lo posee" hasta que se abandona el control. Esto realmente es un recurso "no administrado" y debe ser liberado. Hay algunos tipos de envoltorio útiles para los diversos recursos que se pueden asignar.

no trato con los no-COM código nativo (por ejemplo CLI), a excepción de unas pocas llamadas WinAPI, que son todos C

Cuestiones relacionadas