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

如何不使用委托传递方法并立即调用?内存分析遇异常

问题分析与解决方案

核心问题原因

你看到内存分配为0KB的根本原因不是委托执行顺序问题,而是DoTest0中创建的ushort[]是局部变量,方法执行完毕后就失去了所有引用,成为可回收的垃圾。调用GC.GetTotalMemory(true)时,true参数会强制触发垃圾回收,所以获取after_GetTotalMemory时,这个数组已经被GC回收,导致前后内存数值无变化。

委托的Invoke()是同步执行的,和普通函数调用的执行顺序完全一致,不存在延迟或乱序的情况,这是你对委托的误解点。

修正方案

要正确检测内存分配,需确保测试方法中分配的对象在获取after_GetTotalMemory前不会被GC回收,以下是两种可行方案:

方式1:让测试方法返回分配的对象

修改RunMethod为泛型版本,通过返回值保持对象引用:

public static T RunMethod<T>(Func<T> function)
{
    long before_GetTotalMemory = GC.GetTotalMemory(true);
    T result = function.Invoke();
    long after_GetTotalMemory = GC.GetTotalMemory(true);
    
    GD.Print($"GetTotalMemory = {before_GetTotalMemory / 1024.0} - {after_GetTotalMemory / 1024.0} = {(after_GetTotalMemory - before_GetTotalMemory) / 1024.0} kb");
    return result;
}

对应修改测试方法与调用代码:

// Test类中的DoTest0
public ushort[] DoTest0()
{
    return new ushort[1000000];
}

// _Process中的调用
if(Input.IsActionJustPressed("ui_right"))
{
    var keepAlive = Tools.Profiling.RunMethod(DoTest0);
    // 若无需后续使用,可手动释放,但需保证Profiling方法执行完成后再回收
}

方式2:在测试方法中保持对象引用

将数组存储到类级字段中,避免方法结束后失去引用:

public partial class Test : Node
{
    private ushort[] _keepAliveArray; // 类字段保持引用

    public override void _Process(double delta)
    {
        if(Input.IsActionJustPressed("ui_right"))
        {
            Tools.Profiling.RunMethod(DoTest0);
        }
    }

    public void DoTest0()
    {
        _keepAliveArray = new ushort[1000000];
    }
}

此时数组因被类字段引用,不会被GC回收,就能正确检测到内存分配差值。

关于"避免字符串传递方法"的疑问

你担心字符串传递方法会带来额外内存分配的问题是正确的,而委托本身是高效且类型安全的调用方式,性能几乎与直接调用一致,完全不需要替换成反射调用,是该场景下的最优选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:08:31