GC.KeepAlive是否清除OnTimeEvent变量和类类型?

时间:2013-10-03 14:10:00

标签: c# timer garbage-collection

我有一个Timer函数,我从global.asax

中的 Application_Start调用它

这是班级:

public class AlertTimer
{
    public AlertTimer()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    static System.Timers.Timer aTimer = new System.Timers.Timer();
    public static void Start()
    {
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        aTimer.Interval = 30000;
        aTimer.Enabled = true;
        GC.KeepAlive(aTimer);
    }
    public static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        PresenceService ps = new PresenceService();
        ps.GetAbsenceContacts(); //takes 10 seconds
    }
}

现在,我的问题是,如果此类类型 PresenceService ps = new PresenceService(); 在运行完成计时器之后变得干净,或者GC将其保留在内存中并且每次启动一个新类型OnTimedEvent运行的时间。

谢谢!

结论:从代码中删除GC。 TNX!

2 个答案:

答案 0 :(得分:5)

  

现在,我的问题是这个类是否类型为PresenceService ps = new   PresenceService();完成计时器运行后,它会变得干净,   或者GC将其保留在内存中并且每次都开始一个新的   OnTimedEvent运行。

PresenceService的实例将留下范围,因此需要进行垃圾回收。但是,由于GC大部分是不确定的,因此它一直存在于内存中,直到它被回收为止。因此,对于那些做事并有生命周期的对象(比如定时器),最好调用某种类型的“关闭”方法。

然而,我遇到的一个更大的问题是你在网络应用程序中运行计时器的原因,以及为什么你觉得需要直接在垃圾收集器上调用任何方法。这通常表明您的申请不合适。

答案 1 :(得分:2)

ps结束时,OnTimedEvent实例将有资格进行垃圾收集。 1 当然,这是假设PresenceService不以某种方式根据自己的引用(通过静态变量等)。

此外,在这种情况下不需要GC.KeepAlive。原因是aTimer是静态的,因此其生命周期已经与应用程序域绑定。换句话说,aTimer无法在Start方法中的任何一点进行收集,因为它是由静态变量半永久生根的。

GC.KeepAlive用于GC过于激进的情况。当您使用发行版配置编译应用程序并在调试器外部运行它时,GC将标记符合收集条件的对象实例,甚至在它们超出范围之前。例如,即使在ps完成之前,也可以收集GetAbsenceContractsGC.KeepAlive基本上取消了优化。您通常会看到它在非托管互操作方案中使用,您将对象引用传递给非托管API。因为GC不知道在非托管领域发生了什么,它可能会错误地认为不再使用该引用并过早收集它。


1 从技术上讲,这不完全正确。当GC认为不再使用该实例时,该实例有资格进行收集。这与它是否仍在范围内无关。