【发布时间】:2010-12-20 10:33:30
【问题描述】:
我有一些 C# 代码使用 CSharpCodeProvider.CompileAssemblyFromSource 在内存中创建程序集。程序集被垃圾回收后,我的应用程序使用的内存比创建程序集之前更多。我的代码在 ASP.NET Web 应用程序中,但我在 WinForm 中复制了这个问题。我正在使用 System.GC.GetTotalMemory(true) 和 Red Gate ANTS Memory Profiler 来测量增长(示例代码约为 600 字节)。
根据我所做的搜索,听起来泄漏来自新类型的创建,而不是来自我持有引用的任何对象。我发现的一些网页中提到了一些关于 AppDomain 的内容,但我不明白。有人可以解释这里发生了什么以及如何解决它吗?
这是一些泄漏的示例代码:
private void leak()
{
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = false;
parameters.ReferencedAssemblies.Add("system.dll");
string sourceCode = "using System;\r\n";
sourceCode += "public class HelloWord {\r\n";
sourceCode += " public HelloWord() {\r\n";
sourceCode += " Console.WriteLine(\"hello world\");\r\n";
sourceCode += " }\r\n";
sourceCode += "}\r\n";
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, sourceCode);
Assembly assembly = null;
if (!results.Errors.HasErrors)
{
assembly = results.CompiledAssembly;
}
}
更新1:这个问题可能相关:Dynamically loading and unloading a a dll generated using CSharpCodeProvider
更新 2: 试图更多地了解应用程序域,我发现了这个:What is an application domain - an explanation for .Net beginners
更新 3: 澄清一下,我正在寻找一种解决方案,它提供与上述代码相同的功能(编译并提供对生成代码的访问)而不会泄漏内存。看起来解决方案将涉及创建新的 AppDomain 和封送处理。
【问题讨论】:
-
非常酷的问题。我将在今天结束之前提供一个如何使用另一个 AppDomain 执行此操作的示例(我目前正在吃午饭,然后回去工作......)。
-
您打算如何处理生成的程序集?是一次性执行还是要坚持执行?
-
@LightX 我会坚持一段时间并根据需要从中调用成员,但是当有新版本的源代码可用时,我会想转储它并根据新代码创建一个新程序集。如果没有 AppDomain 修复程序,这种重复创建程序集的循环(即使我停止引用旧版本)会导致内存使用量增加。
-
这个函数调用没有“泄漏”。只允许它被垃圾收集。为此,您必须卸载 yiu 已将生成的程序集加载到其中的整个域
标签: c# memory-leaks marshalling appdomain compileassemblyfromsource