查找导致 CannotUnloadAppDomainException 的违规线程

Find offending thread causing CannotUnloadAppDomainException

在我的 C# .Net 4.0 项目中,我使用 AppDomains 加载插件程序集,要求它们工作,然后卸载 AppDomain,这样我就不必将程序集保留在主进程中。

对于一个特定的插件,我在调用 AppDomain.Unload() 时得到 CannotUnloadAppDomainException。我发现这很可能是因为插件启动了一个后台线程,该线程在 catchfinally 块中卡住或花费很长时间(~10 秒)。不幸的是,我不知道线程在哪里。

这只发生在客户的机器上,所以我无法使用我的调试器来提供帮助。但是,如果我能找到更有用的东西来写,我可以给他们一个补丁,将更多信息写入日志文件。

我有插件程序集的源代码,我一直在尝试做一些静态分析和 运行 一些测试,但它非常大,我没能找到它所在的位置陷入 catchfinally.

我的问题:

  1. 有什么方法可以让我在获得 CannotUnloadAppDomainException 后得到一个线程列表,这些线程是 运行 它们在子 AppDomain 中的调用堆栈?

  2. 除了catchfinally块,还有其他代码段可以抛出这个异常吗?

让客户端 运行 PerfView to get a ETW trace of the program when it happens, it should let you get some more detailed information on what is running during the exact moment the exception happens. Here is a set of video tutorials from Channel 9 向您展示如何使用它。

使用 this post (which is a NuGet package) I was able to list all threads still running and their callstacks when the child AppDomain's function was about to return. I did have to temporarily upgrade my app to .NET 4.5 to run with the library, but the source for the library is available on GitHub 中提到的 Microsoft.Diagnostics.Runtime 库,因此可以使用 < .Net 4.5

构建此库

事实证明,当数据库在本地计算机上使用 SSL 时,处理我们的数据库连接的第三方库中存在一个错误,导致几个线程被锁定。