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

AppDomain 由单独的 CLR 线程卸载。当终结器线程正在运行时,该线程无法运行。您收到异常是因为 CLR 注意到卸载线程没有取得进展。它永远不会继续,因为终结器线程在 Unload 调用上被阻塞。

僵局。

您的解决方法确实解决了这个僵局。明确地进行卸载而不是依赖终结器是这里更好的方法。

于 2010-10-31T20:07:04.517 回答