如何在多线程应用程序中正确卸载AppDomain?

时间:2015-07-09 15:47:39

标签: c# .net multithreading appdomain threadabortexception

我正在尝试卸载AppDomain,我得到CannotUnloadAppDomainException

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

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

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

    据我所知,当我打电话

    AppDomain.Unload(subDomain);
    

    然后受影响的域中的所有线程都获得ThreadAbortException

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

    除了两种情况外:

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

    似乎我的应用程序首先执行(可能它会调用一些非托管代码,这就是它没有停止的原因)

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

    我只看到两个选项:

    • 尝试中止我的线程,然后以某种方式重新检查线程的状态。如果它们被停止,那么我可以调用AppDomain.Unload - 它不应该抛出异常。
    • 另一种选择就是致电AppDomain.Unload。可能会抛出异常。然后我可以捕获此异常并重试卸载。由于AppDomain.Unload试图中止所有受影响的线程,因此可能只需重试几次即可。

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

    在.NET中没有更简单,更健壮的方法吗?

1 个答案:

答案 0 :(得分:2)

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

如果由于某种原因你无法控制后台线程,那么很遗憾没有太多可以做的事情。除了this answer

中已经描述过的内容之外

这是我个人可以给你的最佳答案,让你明确优雅地关闭你的子域名。其他任何东西都会变得凌乱。