C# · 12月 27, 2021

c# – C DLL不会与AppDomain卸载

我有一个C#插件,使用一个单独的C DLL.该DLL的唯一引用来自插件本身.父应用程序将所有插件加载到自己的AppDomain中,并在卸载插件时卸载此AppDomain.

我已经检查,当我卸载插件时,我肯定会看到应用程序的内存下降.我也可以删除所有被加载的托管程序集.问题是,当我尝试删除本机DLL时,我只是不断获得访问被拒绝,直到我关闭整个应用程序.

我一直在看这一段时间,但我仍然无法弄清楚为什么这个DLL停留在内存中.

解决方法 AppDomains是一个纯托管代码构造.没有这样的东西存在于本机代码中,Windows也没有任何意见.所以加载本机DLL的范围是这个过程.技术上,pinvoke编组者可以引用对DLL的计数,并确切地跟踪哪个AppDomain触发DLL的加载.然而,它无法判断是否运行使用该DLL的本机代码.可以通过另一个AppDomain中的代码进行的调用来启动本地代码,可能间接通过封送代理.

如果AppDomain经理卸载使用这种方式的DLL,很明显是灾难性的,这是一个令人讨厌的和不可能诊断AccessViolation的事情.特别令人讨厌,因为它可以在AppDomain卸载后触发很长时间.

所以编组者没有实现这种计数,DLL保持加载.只有您可以提供这种不可能发生的保证,您才可以对DLL中运行的代码进行一些控制,以及如何启动.您可以强制DLL卸载,但需要一个黑客. Pinvoke LoadLibrary()自己来获​​取DLL的句柄.并锁定FreeLibrary()两次以强制卸载它. Windows和CLR都看不到你在作弊.您必须确保在此之后无法使用该DLL.