1

我正在尝试卸载 AppDomain 并得到CannotUnloadAppDomainException.

MSDN 提到了可能引发此异常的 3 个原因:

  1. 默认应用程序域,必须在应用程序的生命周期内保持加载。
  2. 具有无法立即停止执行的正在运行线程的应用程序域。
  3. 已卸载的应用程序域。

我的应用程序受到案例 2) 的影响。

它有一些后台线程——例如,我有一个搜索索引线程运行它自己的 Dispatcher。

据我所知,当我打电话时

AppDomain.Unload(subDomain);

然后受影响域中的所有线程都会得到一个ThreadAbortException.

理想情况下,这意味着所有线程都被“杀死”/停止,对吧?

除了以下两种情况:

  • 当一个线程调用一些托管代码时 - 运气不好......
  • 当线程在 finally 语句中执行某些代码时。

似乎我的应用程序是第一个(可能它在后台调用了一些非托管代码,这就是它没有停止的原因)

所以最大的问题是:如果 AppDomain 有多个线程,如何卸载它?

我只看到两个选项:

  • 尝试中止我的线程,然后以某种方式重新检查线程的状态。如果它们被停止,那么我可以调用AppDomain.Unload- 它不应该引发异常。
  • 另一种选择只是简单地调用AppDomain.Unload。可能它会抛出异常。然后我可以捕捉到这个异常并重试卸载。由于AppDomain.Unload尝试中止所有受影响的线程,因此可能重试几次就足够了。

两种解决方案都使用了一些重试机制,这似乎是骇人听闻的。

在 .NET 中没有更简单、更强大的方法吗?

4

1 回答 1

3

您不希望ThreadAbortedExceptions避免这种情况,请考虑某种取消策略。如果您有权访问这些线程或任务,那么您可以在主线程中使用 Cancellation

如果您出于某种原因无法控制后台线程,那么不幸的是,您无能为力。除了此答案中已经描述的内容

这是我个人可以给您的最佳答案,以明确优雅地关闭您的子域。其他任何事情都会变得一团糟。

于 2015-07-09T16:07:52.730 回答