是什么让 t
成为有根引用(留在范围内)? (t
是用户定义的类)
我在 IL spy 中查看,它不是一个常见的捕获变量!
Action runs = null;
while (dummy <= tod.Value.Date)
{
var t = new Task(dummy, _interval);
runs += t.Run;
dummy = dummy.AddDays(1);
}
GC.Collect();
((Action)(() => { runs(); })).BeginInvoke(Result, null);
有人能给我解释一下吗? t
(任务)类如何保持在范围内,是什么让它 Root ,我猜它是运行委托(delegate),但如何?
最佳答案
首先,我应该指出这与范围 没有太大关系,范围 是程序文本的区域,在该区域中可以使用实体的简单名称来引用实体。这是关于可达性。
现在我还没有用内存分析器查看有问题的堆,但是 Task
对象的路径看起来像这样:
Action
(多播)委托(delegate)实例是 GC 根,因为它被runs
(本地)引用。- 此委托(delegate)实例又通过其
_invocationlist
字段保持其各个订阅者处于事件状态,该字段包含对委托(delegate)数组的引用。 - 此数组又包含对单个(单播)
Action
委托(delegate)实例的引用。 - 这些单独的委托(delegate)中的每一个都将是一个封闭实例委托(delegate),具有填充的
_target
字段(它将充当传递的this
引用到调用委托(delegate)时的Task.Run
方法)。该字段将保存对Task
实例的引用。
总结:
runs local
-> Multicast Action object
-> (through _invocationlist field) Array of references to Action objects
-> (through a specific array element) Unicast Action object
-> (through _target field) Task object
更新:
我通过 Ants Memory Profiler 运行了这个,这证实了我的想法:
关于c# - 是什么让委托(delegate)多目标对象留在范围内?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8646573/