是什么让委托多目标对象留在范围内?

时间:2011-12-27 15:57:21

标签: c# .net delegates garbage-collection

是什么让t成为有根参考(留在范围内)? (t是用户定义的类)

我在IL间谍中看到它,它不是一个常见的捕获变量!

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(任务)类如何保持在范围内,是什么使它成为根,我猜它的运行委托,但如何?

1 个答案:

答案 0 :(得分:6)

首先,我应该指出,这与范围并不相关,范围是程序文本的一个区域,人们可以使用其简单名称来引用实体。它涉及可达性

现在我还没有用内存分析器查看有问题的堆,但是Task对象的路径看起来像这样:

  1. Action(多播)委托实例是GC根,因为它由runs(本地)引用。
  2. 此委托实例反过来通过其_invocationlist字段保持其各个订阅者的活动,该字段包含对委托数组的引用。
  3. 此数组依次包含对各个(单播)Action委托实例的引用。
  4. 这些单独的代表中的每一个都将是已关闭实例委托,其中包含已填充的_target字段(将作为this引用传递给Task.Run调用委托时的方法)。该字段将包含对Task实例的引用。
  5. 总结:

        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运行了这个,这证实了我的想法:

    Path to Task object