You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重复执行C#脚本时出现句柄泄漏问题求助

解决CSharpScript重复执行导致的句柄泄漏问题

你遇到的句柄泄漏是因为每次调用CSharpScript.Create或CSharpScript.RunAsync时,都会生成新的动态程序集,这些程序集默认加载到不可回收的上下文里,相关资源(如文件句柄、内存映射句柄)无法被及时释放,哪怕手动触发GC也没用。

解决方案1:复用Script实例(脚本内容固定时)

如果执行的脚本内容不变,只需要创建和编译一次Script,重复执行即可,从根源避免重复生成资源:

using Microsoft.CodeAnalysis.CSharp.Scripting;

// 仅初始化一次脚本
var script = CSharpScript.Create("bool test = true;");
script.Compile();

while (true)
{
    using (var state = script.RunAsync())
    {
        var result = state.Result;
    }
}

解决方案2:使用可回收AssemblyLoadContext(脚本内容动态变化时)

如果每次执行的脚本内容不同,需要用AssemblyLoadContext隔离动态生成的程序集,确保资源可以被卸载:

using System.Runtime.Loader;
using Microsoft.CodeAnalysis.CSharp.Scripting;

while (true)
{
    // 创建可回收的AssemblyLoadContext
    using var alc = new AssemblyLoadContext(null, isCollectible: true);
    var scriptOptions = ScriptOptions.Default.WithAssemblyLoadContext(alc);
    
    using (var state = CSharpScript.RunAsync("bool test = true;", scriptOptions))
    {
        var result = state.Result;
    }
    
    // 显式卸载ALC并触发GC回收资源
    alc.Unload();
    GC.Collect();
    GC.WaitForPendingFinalizers();
}

原因说明

  • 默认情况下,CSharpScript生成的动态程序集会被加载到全局AssemblyLoadContext,这个上下文不可回收,程序集及其关联句柄会一直被进程持有。
  • 可回收AssemblyLoadContext可以单独管理动态程序集,调用Unload()后,该上下文内的所有资源会被标记为可回收,配合GC可以释放相关句柄。

内容的提问来源于stack exchange,提问作者filtrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 00:25:11