提问人:filtrow 提问时间:11/16/2023 最后编辑:dropoutcoderfiltrow 更新时间:11/16/2023 访问量:68
运行 c# 脚本时处理泄漏
Handle leak when running c# scripts
问:
我有一个 .NET 应用程序,用户还可以在其中输入一些 c# 脚本。该脚本在应用程序中重复执行,当发生这种情况时,我看到句柄泄漏。
我使用来自 Microsoft.CodeAnalysis.CSharp.Scripting 的静态类 CSharpScript。 我尝试了一个非常简单的控制台应用程序,但问题仍然存在。 这是我使用的代码:
using Microsoft.CodeAnalysis.CSharp.Scripting;
while (true)
{
var script = CSharpScript.Create("bool test = true;");
script.Compile();
using (var state = script.RunAsync())
{
var result = state.Result;
}
}
以及:
using Microsoft.CodeAnalysis.CSharp.Scripting;
while (true)
{
using (var state = CSharpScript.RunAsync("bool test = true;"))
{
var result = state.Result;
}
}
我还尝试在每次迭代中调用垃圾回收器,但我得到了相同的结果。 在这两个示例中,句柄都飞向天空: 进程监视器中的句柄
答:
0赞
filtrow
11/29/2023
#1
我设法找到了解决问题的方法。经过一番搜索,我发现 EvaluateAsync 在内存中生成一个新程序集,并且无法删除。
我必须使用CSharpCompilation类而不是CSharpScript才能获得相同的结果,而不会发生内存泄漏!这有点棘手,但它效果很好。这里有一个小例子:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System.Reflection;
namespace MyNamespace
{
public class MyData
{
public string Name { get; set; }
public int Age { get; set; }
}
}
class Program
{
static void Main(string[] args)
{
MethodInfo method;
object instance;
string code = @"
using System;
public class DynamicClass
{
public string DynamicMethod(MyNamespace.MyData data)
{
return ""Name: ""+ data.Name + "" Age: "" + data.Age;
}
}
";
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
string assemblyName = Path.GetRandomFileName();
MetadataReference[] references = {
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(MyNamespace.MyData).Assembly.Location) // Aggiunta del riferimento all'assembly contenente MyData
};
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
foreach (Diagnostic diagnostic in result.Diagnostics)
{
Console.WriteLine(diagnostic);
}
return;
}
else
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(ms.ToArray());
Type dynamicType = assembly.GetType("DynamicClass");
instance = Activator.CreateInstance(dynamicType);
method = dynamicType.GetMethod("DynamicMethod");
}
}
while (true)
{
if (method is not null)
{
var data = new MyNamespace.MyData { Name = "John", Age = 30 };
var outRes = method.Invoke(instance, new object[] { data });
Console.WriteLine(outRes);
}
}
}
}
评论