2010-10-31 10 views
6

Quindi, ecco la storia fino ad ora, ho questo lavoratore che usa un AppDomain per eseguire qualche compito. Il dominio è costoso da configurare e smantellare. Così ho creare una cache per-filo di oggetti WeakReference al lavoratore thingy in questo modo:AppDomain.Unload getta in 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 
} 

Il problema che sto avendo è che sembra gettare sempre un'eccezione nella chiamata a AppDomain.Unload quando GC raccoglie:

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

così sto pensando che sia strano, so che non ho niente 'disattivato' in quel dominio ... che cosa è l'affare? Un po 'di scavo e di tentativi ed errori sono arrivato fino a questo:

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

Quindi le mie domande sono:

  1. Will AppDomain.Unload sicuro sempre da un finalizzatore? Perché?
  2. Ho intenzione di sperimentare qualcosa di "indesiderabile" con la soluzione precedente?
+0

Eventuali duplicati di [Perché AppDomain.Unload() errore nel finalizzatore?] (Https://stackoverflow.com/questions/1891480/why-does-appdomain-unload-error-in-finalizer) – Fabian

risposta

10

AppDomain vengono scaricati da un thread CLR separato. Quel thread non può essere eseguito mentre il thread del finalizzatore è in esecuzione. Stai ottenendo l'eccezione perché il CLR nota che il thread di scarico non sta facendo progressi. Non si avvia mai perché il thread del finalizzatore è bloccato nella chiamata Unload.

Deadlock.

La soluzione alternativa risolve effettivamente questo punto morto. Fare lo scarico in modo esplicito invece di fare affidamento su un finalizzatore è l'approccio migliore qui.

+0

Ahh, come Ho sospettato. Concordato che lo scarico esplicito sarebbe migliore; tuttavia, non ho un posto da cui posso scaricare i domini nella cache. Questa era la ragione per WeakReference. –

+0

Abbiamo appena iniziato a farlo dopo aver aggiornato il progetto su .NET 4. 3.5 SP1 non sembra avere questo comportamento per noi. Riesco a capire la logica di questa risposta, quindi sono felice di sistemare il nostro codice rotto. – nbevans

Problemi correlati