【问题标题】:How to properly unload an AppDomain in a multi-threaded application? [duplicate]如何在多线程应用程序中正确卸载 AppDomain? [复制]
【发布时间】:2015-07-09 15:47:39
【问题描述】:

我正在尝试卸载 AppDomain 并收到 CannotUnloadAppDomainException

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

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

我的应用程序遇到了案例 2)。

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

据我所知,当我打电话时

AppDomain.Unload(subDomain);

那么受影响域中的所有线程都会得到一个ThreadAbortException

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

两种情况除外:

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

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

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

我只看到两个选项:

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

这两种解决方案都使用了一些重试机制,这似乎是 hackish。

在 .NET 中没有更简单、更可靠的方法吗?

【问题讨论】:

    标签: c# .net multithreading appdomain threadabortexception


    【解决方案1】:

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

    如果您出于某种原因无法控制后台线程,那么很遗憾,您无能为力。除了this answer 中已经描述的内容

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-24
      • 2012-11-06
      • 2010-09-12
      • 2012-03-24
      • 1970-01-01
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多