定时器和垃圾收集

时间:2015-09-01 01:27:59

标签: c# memory-management memory-leaks timer garbage-collection

说我有这样的课程

class A
{
    private B _objB
    private Timer _timer; // Using System.Timers 

    public A(objB)
    {
        _objB = objB;
        _timer = new Timer();
        _timer.Interval = 1000;
        _timer.Elapsed += SomeEvent;
    }

    public void Begin()
    {
        _timer.start();
    }

    public void End()
    {
        _timer.Dispose();
    }

    public void SomeEvent (object sender, ElapsedEventArgs e)
    {
        if (_objB.Condition())
        {
            // do something
        }
        else 
        {
            _timer.Dispose();
        }
    }
}

现在我的代码中的其他地方在另一个类中我这样做

public void SomeMethod(B objectB)
{
    A objA = new A(objectB);
    objA.Begin();
   // do other stuff
   // objA.End() can be called here but for this example it's not
}

我知道当我退出SomeMethod()的范围时,objA将不会被垃圾收集,因为有一个持续触发的计时器事件。我不确定的是:

1)在SomeEvent中,我点击了else条件并调用了_timer.Dispose(),这会停止触发更多事件,但是这会告诉GC它可以清理定时器,还有objA吗?换句话说,我是否导致任何内存泄漏?

2)是否存在可能导致例外的竞争条件?因此,如果我正在调用_timer.Dispose()并在某种程度上在队列中有另一个计时器事件,那么输入该事件会导致任何异常吗?

我只是不确定我是否正在进行适当的清理以避免内存泄漏。

1 个答案:

答案 0 :(得分:1)

  1. 一般都是正确的。当你处理Timer时,ObjA将有资格获得GC。实际上,垃圾收集器会在下一个垃圾收集周期中收集它。
  2. 请注意,它不会在符合GC条件后立即收集您的对象。垃圾收集器使用其启发式算法来触发垃圾收集。它仅在存在压力时才会发生。实际上当Gen0或Large Object Heap即将溢出时。

    1. 可能..看看here
    2.   

      Dispose()方法重载后可能会发生回调   调用,因为定时器将回调排队以供线程执行   池线程。您可以使用Dispose(WaitHandle)方法重载   等到所有回调都完成。