type - ¿Cómo descargar correctamente un dominio de aplicación usando C#?
webbrowser c# (2)
Tengo una aplicación que carga ensamblados externos sobre los cuales no tengo control (similar a un modelo de complemento donde otras personas crean y desarrollan ensamblados que son utilizados por la aplicación principal). Los carga mediante la creación de nuevos AppDomains para estos ensamblajes y luego, cuando se terminan de usar, el principal AppDomain los descarga.
Actualmente, unloads simplista estos ensamblajes mediante
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch(Exception exception)
{
// log exception
}
Sin embargo, en ocasiones, se producen excepciones durante el proceso de descarga, específicamente CannotUnloadAppDomainException
. Por lo que entiendo, esto se puede esperar, ya que un subproceso en los dominios de aplicación secundarios unloads :
Cuando un hilo llama a Descargar, el dominio de destino se marca para descargar. El subproceso dedicado intenta descargar el dominio y todos los subprocesos en el dominio se anulan. Si un subproceso no se cancela, por ejemplo, porque está ejecutando un código no administrado, o porque está ejecutando un bloque finally, luego de un período de tiempo se lanza una excepción CannotUnloadAppDomainException en el subproceso que originalmente se llamó Descargar. Si el hilo que no pudo abortarse termina, el dominio de destino no se descarga. Por lo tanto, en el dominio .NET Framework versión 2.0 no se garantiza que se descargue, ya que podría no ser posible terminar la ejecución de subprocesos.
Mi preocupación es que si el ensamblaje no está cargado, entonces podría causar una pérdida de memoria. Una posible solución sería eliminar el proceso principal de la aplicación si se produce la excepción anterior, pero prefiero evitar esta acción drástica.
También estaba considerando repetir la llamada de descarga para algunos intentos adicionales. Tal vez un bucle restringido como este:
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch (CannotUnloadAppDomainException exception)
{
// log exception
var i = 0;
while (i < 3) // quit after three tries
{
Thread.Sleep(3000); // wait a few secs before trying again...
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch (Exception)
{
// log exception
i++;
continue;
}
break;
}
}
¿Esto tiene sentido? ¿Debería siquiera molestarme en intentar descargar de nuevo? ¿Debo probarlo una vez y seguir adelante? ¿Hay algo más que deba hacer? Además, ¿hay algo que se pueda hacer desde el dominio de aplicación principal para controlar el ensamblaje externo si todavía hay subprocesos en ejecución (tenga en cuenta que otros están escribiendo y ejecutando este código externo)?
Estoy tratando de entender cuáles son las mejores prácticas al administrar múltiples AppDomains.
He tratado con un problema similar en mi aplicación. Básicamente, no puedes hacer nada más para forzar que el AppDomain
de aplicación se caiga y que Unload
no lo haga.
Básicamente, se llama a la cancelación de todos los subprocesos que ejecutan código en el AppDomain
, y si ese código está atascado en un finalizador o código no administrado, no hay mucho que se pueda hacer.
Si, en función del programa en cuestión, es probable que el código finalizador / no administrado finalice más tarde, puede volver a llamar a Unload
. De lo contrario, puede filtrar el dominio a propósito o completar el proceso.
Intente hacer GC.Collect () si no descarga el dominio.
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch (CannotUnloadAppDomainException)
{
GC.Collect();
AppDomain.Unload(otherAssemblyDomain);
}