如何不使用委托传递方法并立即调用?内存分析遇异常
问题分析与解决方案
核心问题原因
你看到内存分配为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
相关产品推荐
相关产品推荐

