martes, 3 de junio de 2014

Receta No. 3-9 en C#: Descarga de Assemblies y Dominios de Aplicación

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente en C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

Esta receta estará enfocada en una exploración más detallada acerca del proceso de descarga (unload) de assemblies y dominios de aplicación. Veremos algunos casos excepcionales del método static Unload de la clase AppDomain, como: generación de excepciones, descarga assemblies cargados en el dominio de aplicación, hilos de ejecución (threads) asociados al dominio de aplicación, en otros.

1. Problema

Requerimos de un método de descarga de assemblies y dominios de aplicación para las aplicaciones desarrolladas hasta este punto (recetas 3-1 hasta 3-8). El objetivo consiste en mejorar el uso eficiente de los recursos máquina (espacio en memoria de trabajo y ciclos de procesador) del dominio de aplicación anfitrión.

2. Solución

Los programadores expertos nos han sugerido solucionar este problema a través del uso del método Unload de la clase AppDomain. Este método, como veremos más adelante, se le ha de especificar como argumento el dominio de aplicación que queremos descargar de la CLR. Pasemos a la siguiente sección para ver cómo funciona.

3. Discusión de la solución

El método Unload [3] posee la siguiente firma:

public static void Unload(AppDomain domain)

Descripción puntual:
  • Modificador static: Es un método estático.
  • domain: recibe como parámetro una referencia de clase AppDomain, el cual corresponde con el dominio de aplicación (junto con los assemblies) a descargar de la CLR.
  • Tipo de retorno void: este método no retorna ningún valor finalizada su llamada.
Este método además de descargar el dominio especificado como argumento, también descarga, de paso, los assemblies asociados a ese mismo dominio de aplicación; y como nos informan en [1] es el único modo de lograrlo. La misma fuente nos aconseja:
This might seem like a heavy-handed and inflexible approach, but with appropiate planning of your applicacion domain, the assembly loading structure, and the runtine dependency of your code on that application domain, it is not overly restrictive.
Continuando, es posible descargar cualquier dominio de aplicación y sus assemblies asociados, sin embargo, hay un dominio de aplicación el cual no podemos descargar y es el creado por la CLR en el momento de su inicialización. Miremos lo que ocurre si intentamos ir en contra de este principio:

Archivo de código fuente DescargarAppDomainAnfitrion.cs [enlace alternativo]:

En la línea 9 obtenemos la referencia del dominio de aplicación actual (anfitrión: el que crea la CLR al inicio de la aplicación) con la sentencia: 

AppDomain appDomainAnfitrion = AppDomain.CurrentDomain;

Casi que enseguida, en la línea 12, hacemos un intento de descarga del dominio de aplicación localizado en la referencia appDomainAnfitrion:

AppDomain.Unload(appDomainAnfitrion);

Esta invocación del método Unload va a generar la excepción CannotUnloadAppDomainException [4] (N:System) por el hecho de intentar descargar un dominio de aplicación, en especial, como en nuestro caso: el dominio de aplicación anfitrión.

Compilación:


  1. csc /target:exe DescargarAppDomainAnfitrion.cs

> Prueba de ejecución.

Resultado:
Intento de descarga de dominio de aplicación anfitrión en C#.
Figura 1. Intento de descarga de dominio de aplicación anfitrión en C#.

Por otro lado, de manera implícita el método Unload pasa a detener cualquier de los hilos de ejecución (threads) asociados con el dominio de aplicación. Esto lo logra a través de repetidas invocaciones al método Thread.Abort [5] sobre cada hilo de ejecución.

Otro de los elementos (miembros) de la clase AppDomain para controlar la descarga de un dominio de aplicación es el método IsFinalizaingForUnload [5]:
Indicates whether this application domain is unloading, and the objects it contains are being finalized by the common language runtime.

4. Práctica: Código Fuente C#

Retomo el ejemplo presentado en la receta 3-1 (Receta No. 3-1 en C#: Creación de un Dominio de Aplicación (Application Domain)) para demostrar el proceso de descarga de un dominio de aplicación usando el método Unload de AppDomain.

Archivo de código fuente DescargaAppDomain.cs [enlace alternativo]:

En la línea 24 creamos un nuevo dominio de aplicación con la sentencia:

AppDomain dominio = AppDomain.CreateDomain("NuevoDominio");

Presentamos en la salida estándar varios de los datos asociados con el dominio de aplicación anfitrión y el recién creado (líneas 27 y 26, respectivamente):

Console.WriteLine("Dominio anfitrión: {0}", AppDomain.CurrentDomain.FriendlyName.ToString());
Console.WriteLine("Dominio huésped: {0}\n", dominio.FriendlyName.ToString());

En la línea 30 ocurre la el evento esperado: la descarga del dominio de aplicación dominio:

AppDomain.Unload(dominio);
En el bloque try-catch (líneas 33-46) intentamos acceder a la información del dominio recién descargado. Este intento acaba con la generación de la excepción AppDomainUnloadedException.

Compilación:


  1. csc /target:exe DescargaAppDomain.cs

> Prueba de ejecución.

Creando un nuevo AppDomain:
Dominio anfitrión: prog.exe
Dominio huésped: NuevoDominio

Dominio anfitrión: prog.exe
System.AppDomainUnloadedException
El dominio de aplicación `dominio` no existe.

5. Conclusiones

En la transición de la preparación de esta receta aprendimos a descargar un dominio de aplicación. También fue importante las consideraciones a tener en cuenta cuando se trata de descargar un dominio de aplicación: descarga implícita de assemblies, finalización de hilos de ejecución, generación de excepciones. En el ejemplo de la sección práctica vimos que intentar acceder a información de un dominio que ya no se encuentra cargado en la CLR, genera la excepción AppDomainUnloadedException.

6. Glosario

  • AppDomain
  • Carga
  • CLR
  • Descarga
  • Dominio de aplicaicón

7. Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: AppDomain Class (System) - http://msdn.microsoft.com/en-us/library/System.AppDomain(v=vs.110).aspx
[3]: AppDomain.Unload Method (System) - http://msdn.microsoft.com/en-us/library/system.appdomain.unload(v=vs.110).aspx
[4]: CannotUnloadAppDomainException Class (System) - http://msdn.microsoft.com/en-us/library/system.cannotunloadappdomainexception(v=vs.110).aspx
[5]: Thread.Abort Method (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.thread.abort(v=vs.110).aspx
[6]: AppDomain.IsFinalizingForUnload Method (System) - http://msdn.microsoft.com/en-us/library/system.appdomain.isfinalizingforunload(v=vs.110).aspx
[7]: Receta No. 3-1 en C#: Creación de un Dominio de Aplicación (Application Domain) - http://ortizol.blogspot.com/2014/05/receta-no-3-1-en-c-creacion-de-un.html


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.