如何从主AppDomain卸载程序集?

Der*_*ker 42 .net c# appdomain

我想知道如何卸载加载到主AppDomain中的程序集.

我有以下代码:

var assembly = Assembly.LoadFrom( FilePathHere );
Run Code Online (Sandbox Code Playgroud)

当我完成时,我需要/希望能够卸载这个程序集.

谢谢你的帮助.

Phi*_*eck 34

您无法从appdomain卸载程序集.您可以销毁appdomains,但是一旦将程序集加载到appdomain中,它就会存在于appdomain的生命周期中.

请参阅Jason Zander关于为何没有Assembly.Unload方法的解释

如果您使用的是3.5,则可以使用AddIn Framework来更轻松地管理/调用不同的AppDomain(您可以卸载,卸载所有程序集).如果您之前使用的是版本,则需要自己创建一个新的appdomain来卸载它.


小智 23

我也知道这已经很老了,但可能会帮助有这个问题的人!这是我发现的一种方法!而不是使用:

var assembly = Assembly.LoadFrom( FilePathHere );
Run Code Online (Sandbox Code Playgroud)

用这个:

var assembly = Assembly.Load( File.ReadAllBytes(FilePathHere));
Run Code Online (Sandbox Code Playgroud)

这实际上加载了程序集文件的"内容",而不是文件本身.这意味着程序集文件上没有文件锁!所以现在它可以复制,删除或升级而无需关闭您的应用程序或尝试使用单独的AppDomain或Marshaling!

PROS:使用1个代码修复非常简单! 缺点:不能使用AppDomain,Assembly.Location或Assembly.CodeBase.

现在您只需要销毁在程序集上创建的任何实例.例如:

assembly = null;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ade 15

如果不卸载整个AppDomain,则无法卸载程序集.原因如下:

  1. 您正在应用程序域中运行该代码.这意味着可能存在呼叫站点和调用堆栈,其中包含期望继续工作的地址.

  2. 假设您确实设法跟踪程序集的所有句柄和对已运行代码的引用.假设您没有使用代码,一旦成功释放了程序集,您就只释放了元数据和IL.JIT代码仍然在app域加载器堆中分配(JIT'd方法按照调用它们的顺序在缓冲区中按顺序分配).

  3. 最后一个问题涉及已加载共享的代码,否则更正式地称为"域中立"(在ngen工具上签出/共享).在此模式下,生成程序集的代码将从任何应用程序域执行(没有硬连线).

建议您自然地围绕应用程序域边界设计应用程序,完全支持卸载.


Nip*_*pun 10

您应该将临时程序集加载到另一个程序集中AppDomain,当不使用时,您可以卸载它AppDomain.这是安全和快速的.

  • 请参阅AppDomain.DoCallback并查看MarshalByRefObject:您创建一个MarshalByRefObject"调用者",其方法可以执行您想要的操作并在其可变字段中返回一些内容,您创建一个临时AppDomain并调用dom.DoCallback(invoker.DoSomething)来实现此目的对象做你想做的事; 然后你从你的appdomain中的调用者收集结果并卸载临时域. (2认同)

Kho*_*oth 5

如果您想拥有可以在之后卸载的临时代码,根据您的需要,DynamicMethod该类可能会执行您想要的操作。不过,这并没有给你上课。