GC根和局部变量

时间:2011-12-07 01:41:10

标签: c# garbage-collection gc-roots

在查看Timer documentation时,我使用以下评论运行了以下示例:

    // Normally, the timer is declared at the class level,
    // so that it stays in scope as long as it is needed.
    // If the timer is declared in a long-running method,  
    // KeepAlive must be used to prevent the JIT compiler 
    // from allowing aggressive garbage collection to occur 
    // before the method ends. You can experiment with this
    // by commenting out the class-level declaration and 
    // uncommenting the declaration below; then uncomment
    // the GC.KeepAlive(aTimer) at the end of the method.
    //System.Timers.Timer aTimer;
    code in between
    // If the timer is declared in a long-running method, use
    // KeepAlive to prevent garbage collection from occurring
    // before the method ends.
    //GC.KeepAlive(aTimer);

这是否意味着C#中的GC被允许垃圾收集局部变量,即使它会产生副作用?可能是因为我之后没有再次访问计时器,GC可以提前收集它?

如果我理解正确的话,我不确定我是这种优化的粉丝(但我可能不会这样做;)

2 个答案:

答案 0 :(得分:2)

是的,在最后一次使用变量之后,GC可能会在结束范围之前收集局部变量。将GC.KeepAlive放在方法的末尾可确保变量在KeepAlive调用之前处于“活动状态”。

C#是命令式语言,所以GC的设计并不是为了解副作用。

答案 1 :(得分:1)

据我了解GC,它会在下一个GC周期中标记它认为不再需要作为垃圾收集候选者的任何变量或对象。我不确定我是否理解这里的特定应用程序,但我知道有些情况下GC可能会在需要时标记要收集的资源(但由于编写代码的方式不会出现这种情况)。 / p>

通常,在方法期间,对象或变量在方法调用期间保持在范围内,但如果方法调用持续的时间长于GC循环之间的时间,则GC可能会将您的Timer对象视为超出范围并标记它收集。添加GC.KeepAlive方法会强制GC等待方法退出,然后再对Timer对象执行操作。