AppDomain.Unload 抛出终结器?
Posted
技术标签:
【中文标题】AppDomain.Unload 抛出终结器?【英文标题】:AppDomain.Unload throws in Finalizer? 【发布时间】:2010-10-31 19:34:56 【问题描述】:这就是目前为止的故事,我有一个使用 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);
所以我的问题是:
-
AppDomain.Unload 是否总是从终结器失败?为什么?
使用上述解决方法我会遇到任何“不受欢迎”的事情吗?
【问题讨论】:
Why does AppDomain.Unload() error in finalizer?的可能重复 【参考方案1】:AppDomain 由单独的 CLR 线程卸载。当终结器线程正在运行时,该线程无法运行。您收到异常是因为 CLR 注意到卸载线程没有取得进展。它永远不会继续,因为终结器线程在 Unload 调用上被阻塞。
死锁。
您的解决方法确实解决了这个僵局。明确地进行卸载而不是依赖终结器是这里更好的方法。
【讨论】:
啊,正如我所怀疑的那样。同意显式卸载会更好;但是,我没有可以卸载缓存域的地方。这就是 WeakReference 的原因。 在将项目升级到 .NET 4 后,我们才刚刚开始获得它。3.5 SP1 似乎对我们没有这种行为。我可以理解这个答案中的逻辑,所以很高兴修复我们损坏的代码。以上是关于AppDomain.Unload 抛出终结器?的主要内容,如果未能解决你的问题,请参考以下文章