Roslyn - OutOfMemoryException 由于内存中加载的程序集

Posted

技术标签:

【中文标题】Roslyn - OutOfMemoryException 由于内存中加载的程序集【英文标题】:Roslyn - OutOfMemoryException due to assemblies loaded in memor 【发布时间】:2021-12-13 08:32:03 【问题描述】:

我们正在对大量(数千个)C# 项目进行广泛的代码分析。但是尽管我们没有调用 Solution.Emit() 方法,程序集仍然被加载到内存中。 还有其他方法也会导致这种行为吗?是否有可能在不将程序集加载到内存中的情况下创建编译并检索其符号? 希望我们能以某种方式避免创建单独的应用程序域并卸载它们。

【问题讨论】:

您的代码中是否有任何类实现IDisposable?如果有,请检查您是如何处理资源的。 据我所知,已经加载的程序集无法卸载,因此首先我们需要防止正在加载程序集。 本身不是,但您应该能够完成创建一个新的 AppDomain。检查我的答案,如果你觉得有用,请标记它。请注意,由于缺少示例 minimal reproducible example,我只能为您提供一些应该能够指导您的通用代码。 【参考方案1】:

看起来你的方法是错误的,你很可能在主 AppDomain 中加载程序集。

但是文档How to: Load and unload assemblies 说要卸载程序集,您需要卸载加载这些程序集的完整应用程序域。它还链接到How to: Unload an Application Domain

所以你应该:

    为程序集创建一个新的应用程序域 将程序集加载到新的 AppDomain 中 进行代码分析 卸载该程序集特定的应用程序域

这是文档中的代码:

Console.WriteLine("Creating new AppDomain.");
AppDomain domain = AppDomain.CreateDomain("MyDomain", null);

Console.WriteLine("Host domain: " + AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("child domain: " + domain.FriendlyName);
try

    AppDomain.Unload(domain);
    Console.WriteLine();
    Console.WriteLine("Host domain: " + AppDomain.CurrentDomain.FriendlyName);
    // The following statement creates an exception because the domain no longer exists.
    Console.WriteLine("child domain: " + domain.FriendlyName);

catch (AppDomainUnloadedException e)

    Console.WriteLine(e.GetType().FullName);
    Console.WriteLine("The appdomain MyDomain does not exist.");

【讨论】:

这似乎可行,但会对性能产生巨大影响。 为了减少建议的解决方案对性能的影响,您可以分析创建的 AppDomain 中的一些程序集,然后将其卸载,将其重新用于一些程序集。只需根据您当前的资源(内存/cpu/时间)找到您的最佳位置

以上是关于Roslyn - OutOfMemoryException 由于内存中加载的程序集的主要内容,如果未能解决你的问题,请参考以下文章

Roslyn

RyuJIT 和 Roslyn 有啥区别?

Roslyn

使用 Roslyn 生成格式良好的语法

Roslyn - 如何用多个节点替换多个节点?

属性挂钩 MSBuild/Roslyn