我有一个使用单独的C++ DLL的C#插件.对该DLL的唯一引用来自插件本身.父应用程序将所有插件加载到自己的AppDomain中,并在卸载插件时卸载此AppDomain.
我已经检查过,当我卸载插件时,我肯定会看到应用程序的内存丢失.我还能够删除所有已加载的托管程序集.问题是,当我尝试删除本机DLL时,我只是不断访问拒绝,直到我关闭整个应用程序.
我已经看了一段时间,但我仍然无法弄清楚为什么这个DLL留在内存中.
Han*_*ant 20
AppDomains是纯托管代码构造.本机代码中不存在类似内容,Windows也不了解它.因此,加载的本机DLL的范围就是进程.从技术上讲,pinvoke marshaller可以引用计数DLL并准确跟踪哪个AppDomain触发了DLL的加载.然而,它无法判断是否正在运行使用该DLL的本机代码.可以通过另一个 AppDomain中的代码调用启动的本机代码,可能通过封送的委托间接调用.
如果AppDomain管理器卸载以这种方式使用的DLL,那将是一个令人讨厌且无法诊断AccessViolation的灾难.特别讨厌,因为它可以在AppDomain卸载后触发很长时间.
所以marshaller没有实现那种计数,DLL保持加载状态.只有您可以保证不会发生这种情况,您可以控制DLL中运行的代码以及它如何启动.您可以强制DLL卸载但它需要一个hack.Pinvoke LoadLibrary()自己来获取DLL的句柄.并且两次将FreeLibrary()旋转,以强行卸载它.Windows和CLR都看不到你在作弊.您必须确保在此之后无法使用DLL.
AFAIK(引擎盖下)本机DLL需要通过Win32 API加载LoadLibrary...它将它们直接加载到进程内存中 - 如果.NET应用程序不是特定于AppDomain... ... LoadLibrary一无所知AppDomain(这是纯粹是特定于.NET的)...因此卸载AppDomain不一定卸载本机DLL ...
关于这种情况的有趣讨论:
如果您可以更改相应插件的实现,那么您将实现"晚期本机绑定",这将解决您看到的问题:
| 归档时间: |
|
| 查看次数: |
3729 次 |
| 最近记录: |