7

これまでの話ですが、AppDomain を使用して何らかのタスクを実行するこのワーカーがあります。ドメインのセットアップと破棄には費用がかかります。したがって、スレッドごとに WeakReference オブジェクトのキャッシュをワーカーに次のように作成します。

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
}

私が抱えている問題は、GC が収集するときに AppDomain.Unload の呼び出しで常に例外をスローするように見えることです。

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

だから私はそれが奇妙だと思っています、私はそのドメインで何も「実行」していないことを知っています...どうしたのですか?少し掘り下げて試行錯誤した結果、次のようになりました。

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

だから私の質問は:

  1. AppDomain.Unload はファイナライザーから常に失敗しますか? なんで?
  2. 上記の回避策で「望ましくない」ことはありますか?
4

1 に答える 1

12

AppDomains は、別の CLR スレッドによってアンロードされます。ファイナライザ スレッドの実行中は、そのスレッドを実行できません。アンロード スレッドが進行していないことを CLR が認識するため、例外が発生しています。Unload 呼び出しでファイナライザー スレッドがブロックされているため、処理が開始されません。

デッドロック。

あなたの回避策は確かにそのデッドロックを解決します。ここでは、ファイナライザーに頼るのではなく、明示的にアンロードを行う方が良い方法です。

于 2010-10-31T20:07:04.517 に答える