卸载装配了Assembly.LoadFrom()的程序集

pro*_*eek 51 c# garbage-collection load gettype

我需要检查加载dll后运行GetTypes()的时间量.代码如下.

Assembly assem = Assembly.LoadFrom(file);
sw = Stopwatch.StartNew();
var types1 = assem.GetTypes();
sw.Stop();
double time1 = sw.Elapsed.TotalMilliseconds;
Run Code Online (Sandbox Code Playgroud)

我想卸载并重新加载dll以检查再次运行GetTypes()所花费的时间.

  • 我该如何卸载它?assem = null够好吗?
  • 是否有一种明确的方法来调用垃圾收集器来回收分配给assem的资源?

小智 69

你可以使用另一个AppDomain吗?

AppDomain dom = AppDomain.CreateDomain("some");     
AssemblyName assemblyName = new AssemblyName();
assemblyName.CodeBase = pathToAssembly;
Assembly assembly = dom.Load(assemblyName);
Type [] types = assembly.GetTypes();
AppDomain.Unload(dom);
Run Code Online (Sandbox Code Playgroud)

  • 对我失败:它抛出dom.Load一个"FileNotFoundException".有趣的是文件确实存在,并且异常消息包含文件的确切版本(不是1.0.0.0,所以我确定它最终找到了我的文件......). (8认同)
  • 在我的例子中,"FileNotFoundException"是由其中一个引用的程序集引起的.我最终使用Assembly.ReflectionOnlyLoadFrom与一个方法相结合,该方法将所有引用的程序集加载到仅反射上下文中. (2认同)

slf*_*fan 34

遗憾的是,加载后无法卸载组件.但是您可以卸载AppDomain.您可以做的是创建一个新的AppDomain(AppDomain.CreateDomain(...)),将程序集加载到此appdomain中以使用它,然后在需要时卸载AppDomain.卸载AppDomain时,将卸载已加载的所有程序集.(见参考)

要调用垃圾收集器,您可以使用

GC.Collect(); // collects all unused memory
GC.WaitForPendingFinalizers(); // wait until GC has finished its work
GC.Collect();
Run Code Online (Sandbox Code Playgroud)

GC在后台线程中调用终结器,这就是为什么你必须等待并再次调用Collect()以确保删除所有内容.

  • 我正在加载(并可能正在卸载)数十个dll。创建70个AppDomains会对性能产生什么影响(以及其他相关影响)?如果可能,我应该避免这样做吗? (2认同)

Har*_*dik 34

而不是使用LoadFrom()LoadFile()可以使用LoadFile.ReadAllBytes().有了它,它不使用汇编文件,但会读取它并使用读取数据.

然后你的代码就像

Assembly assem = Assembly.Load(File.ReadAllBytes(filePath));
sw = Stopwatch.StartNew();
var types1 = assem.GetTypes();
sw.Stop();
double time1 = sw.Elapsed.TotalMilliseconds;
Run Code Online (Sandbox Code Playgroud)

这里我们无法卸载该文件,除非卸载其中包含的所有域.

希望这可以帮助.:)

  • 您不能将字节数组传递给`Assembly.LoadFrom()`.我编辑了你的帖子,但有人改回来了. (2认同)
  • @tapatio它的工作原理是因为Hardik正在使用`Assembly.Load`而不是`Assembly.LoadFrom`. (2认同)
  • @Hardik 是正确的:Assembly Load 方法保存对加载的文件的引用,防止该文件被另一个进程覆盖或删除。因此,使用不包含引用的 File 对象的 ReadAllBytes 方法是一种巧妙的解决方法。读取这些字节并关闭文件后,结果将传递给 Assembly Load 方法。相当聪明! (2认同)
  • 但是,当您的程序集具有依赖项时,这将不起作用。我们将得到 LoaderExceptions。这种情况该怎么办? (2认同)