2010-10-31 11 views
6

Así que aquí está la historia hasta ahora, tengo esta cosa de trabajador que usa un Dominio de aplicación para realizar alguna tarea. El dominio es costoso de configurar y desmontar. Así se crea una memoria caché cosita por subproceso de objetos WeakReference al trabajador, así:AppDomain.Unload throws en Finalizer?

class Worker 
{ 
    [ThreadStatic] 
    static Dictionary<string, WeakReference> _workers; 

    public static Worker Fetch(...) { you get the idea } 

    private AppDomain _domain; 
    public Worker(...) 
    { 
     _domain = AppDomain.Create(...); 
    } 

    ~Worker() 
    { 
     AppDomain.Unload(_domain); 
    } 

    // bla bla bla 
} 

El problema que estoy teniendo es que parece que tirar siempre una excepción en la llamada a AppDomain.Unload cuando recoge GC:

System.CannotUnloadAppDomainException: Error while unloading appdomain. (Exception from HRESULT: 0x80131015)" 

así que estoy pensando que es extraño, sé que no tengo nada de 'funcionamiento' en ese dominio ... ¿Cuál es el trato? Un poco de excavación y de ensayo y error que se le ocurrió esto:

~Worker() 
    { 
     new Action<AppDomain>(AppDomain.Unload) 
      .BeginInvoke(_domain, null, null); 
    } 

Así que mis preguntas son:

  1. Will AppDomain.Unload siempre fallan desde un finalizador? ¿Por qué?
  2. ¿Voy a experimentar algo "indeseable" con la solución anterior?
+0

Posible duplicado de [¿Por qué AppDomain.Unload() error en el finalizador?] (Https://stackoverflow.com/questions/1891480/why-does-appdomain-unload-error-in-finalizer) – Fabian

Respuesta

10

Los AppDomains se descargan mediante un hilo CLR diferente. Ese hilo no se puede ejecutar mientras se ejecuta el hilo del finalizador. Estás recibiendo la excepción porque el CLR nota que el hilo de descarga no está progresando. Nunca se pone en marcha porque el hilo del finalizador está bloqueado en la llamada de Descarga.

Deadlock.

Su solución resuelve ese punto muerto. Hacer la descarga de forma explícita en lugar de confiar en un finalizador es el mejor enfoque aquí.

+0

Ahh, as Sospeché. Acordó que la descarga explícita sería mejor; sin embargo, no tengo un lugar desde el cual pueda descargar los dominios en caché. Esa fue la razón de WeakReference. –

+0

Recién comenzamos a obtenerlo después de actualizar el proyecto a .NET 4. 3.5 SP1 no parecía tener este comportamiento para nosotros. Sin embargo, puedo entender la lógica de esta respuesta, por lo que me complace arreglar nuestro código roto. – nbevans

Cuestiones relacionadas