2010-10-31 42 views
6

Donc, voici l'histoire jusqu'à présent, j'ai ce truc de travailleur qui utilise un AppDomain pour effectuer une tâche. Le domaine est coûteux à configurer et à démonter. Je crée donc un cache par thread d'objets WeakReference au travailleur thingy comme ceci:AppDomain.Unload renvoie dans 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 
} 

Le problème que je vais avoir est que semble toujours jeter une exception dans l'appel à AppDomain.Unload lorsque GC recueille:

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

Je pense que ce bizarre, je sais que je n'ai rien « en cours d'exécution » dans ce domaine ... ce qui est l'affaire? Un peu de creuser et de tâtonnements je suis venu avec ceci:

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

Mes questions sont les suivantes:

  1. Will AppDomain.Unload échouent toujours d'un Finalizer? Pourquoi? Est-ce que je vais expérimenter quelque chose d'indésirable avec la solution de contournement ci-dessus?
+0

Copie possible de [Pourquoi l'erreur AppDomain.Unload() dans le finaliseur?] (Https://stackoverflow.com/questions/1891480/why-does-appdomain-unload-error-in-finalizer) – Fabian

Répondre

10

Les domaines d'application sont déchargés par un thread CLR distinct. Ce thread ne peut pas s'exécuter pendant que le thread finalizer est en cours d'exécution. Vous obtenez l'exception car le CLR remarque que le thread de déchargement ne progresse pas. Il ne démarre jamais parce que le thread finalizer est bloqué sur l'appel Unload.

Impasse.

Votre solution de contournement résout en effet ce blocage. Faire le déchargement explicitement au lieu de compter sur un finaliseur est la meilleure approche ici.

+0

Ahh, as J'ai suspecté. Est convenu que le déchargement explicite serait préférable; Cependant, je n'ai pas d'endroit à partir duquel je peux décharger les domaines mis en cache. C'était la raison du WeakReference. –

+0

Nous venons de commencer à l'obtenir après la mise à niveau du projet vers .NET 4. 3.5 SP1 ne semblait pas avoir ce comportement pour nous. Je peux comprendre la logique dans cette réponse si je suis si heureux de réparer notre code brisé. – nbevans