如何使用C#卸载.dll文件?

3

我正在使用.dll文件引用我的应用程序。 我希望在按钮点击事件中卸载.dll文件。 该如何实现???

3个回答

8

你不能卸载单个程序集 - 你必须卸载整个 AppDomain。换句话说,你需要在一个新的 AppDomain 中加载你的其他程序集(和相关代码),然后当你想要卸载它时,你卸载 AppDomain

当然,这使得生活变得更加困难,因为你必须担心在 AppDomains 之间调用的封送调用 - 但这是 .NET 允许的唯一方式。


这是一个后台WinApp,因为只有通过在任务管理器中结束它才能关闭应用程序。即使像那样杀死了应用程序,.dll也不会被卸载。这就是为什么我想强制卸载它的原因。 还有其他方法吗? - Anuya
3
如果你的进程已经结束,那么它就不应该继续占用这个DLL文件。你确定这不是其他进程的原因吗?使用SysInternals工具进行检查。 - Jon Skeet
BTW,我认为在应用程序域之间进行编组的类型/实例存在限制。 - pero
@Peter:感谢您在喝咖啡前发现了这个笔误。是的,有一些限制和问题等,这也是使它变得如此困难的原因 :( - Jon Skeet

3
正如Jon Skeet所写,您无法卸载DLL,但可以在另一个AppDomain中加载DLL,然后卸载AppDomain。这是唯一的方法。
然而,有些事情需要注意,因为您自然会跨AppDomain调用函数。这可以通过两种不同的方式发生。
如果您从一个AppDomain(称为A)获取对在AppDomain B中实例化的对象的引用,则默认行为是该对象跨AppDomain边界进行序列化。这意味着A访问的对象实例与B访问的对象实例不同,并且在A中进行的修改不会反映在B中,除非您提供将对象发送回的功能。这要求对象标记为Serializable。
但是,您可以通过让类继承MarshalByRefObject来避免序列化。如果在AppDomain B中构造了对象,并从AppDomain A中调用,则调用将跨越AppDomain边界。它仍将是相同的物理线程,因此您没有跨进程调用或COM跨公寓调用的线程切换开销。
但是,如果您在B中构造了一个由A中的对象引用的对象,但B中的对象未被访问5分钟,那么该对象将被处理。可以在MarshalByRefObject.InitializeLifetimeService()中覆盖此行为。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接