如何优雅地清理计时器?

时间:2017-11-24 10:46:03

标签: c#

我有一个通过构造函数安装计时器的类。

public class ScanInput
{
   private Timer m_Timer;
   :
   public ScanInput(bool bAuto)
   {
      Auto = bAuto;

      if (bAuto)
      {
         m_Timer = new Timer();

         m_Timer.Interval = 1000 * DEFAULTTIMERSECONDS;
         m_Timer.Enabled = true;
         m_Timer.Tick += new EventHandler(OnTimerTick);
      }
      else
         m_Timer = null;
   }
   :
   protected void OnTimerTick(object sender, EventArgs e)
   {
       :
   }
}

当此对象超出正在运行的计时器的范围时会发生什么?我是否必须实现一个IDisposable接口才能优先停止计时器并清理它?

2 个答案:

答案 0 :(得分:0)

如果您的类有IDisposable个字段,那么它本身应该实现IDisposable以允许您的类的用户释放非托管资源(在您的情况下是底层OS计时器资源)。

Microsoft解释了Dispose Pattern

  

DO 在包含一次性类型实例的类型上实现Basic Dispose Pattern。有关基本模式的详细信息,请参阅基本处理模式部分。

如果你没有在课堂上实施IDisposable,就会发生两件事:

  1. 计时器使用的非托管资源在不再使用时不会被清除。相反,这会在计时器实例被定时器具有终结器时被垃圾收集后发生。

  2. 定时器非托管资源通过最终确定来清理,需要终结器线程的额外工作,这是最好的避免。

  3. 虽然你当然应该尝试编写最佳代码,但这些点中的任何一点都不会对小应用程序造成太大影响。

    在您的案例中,实施IDisposable非常简单:

    sealed class ScanInput : IDisposable
    {
        public void Dispose()
        {
            m_Timer.Dispose();
        }
    }
    

    可以处置已经放置的物品,这样就不会保护m_Timer.Dispose()的呼叫。但是,如果已经处置ObjectDisposedException并且该方法不再能够执行其工作,您可能希望在其他一些方法中抛出ScanInput

    该类是密封的,以避免实现IDisposable和允许派生成员覆盖所处理的内容的复杂性。

    为了使这个有用,你当然必须在完成使用它之后处理ScanInput实例。否则,定时器非托管资源的清理只会在您控制之外发生。

答案 1 :(得分:0)

  

我是否必须实现IDisposable接口才能优雅地停止   计时器首先清理它?

使用Dispose()实例后,应该调用Timer方法。是的,你可以在你的类上实现IDisposable并实现Dispose()方法,在你的类型的dispose实现中你应该调用timer dispose