【问题标题】:Is it necessary to dispose System.Timers.Timer if you use one in your application?如果您在应用程序中使用 System.Timers.Timer,是否有必要处理它?
【发布时间】:2009-01-24 09:01:12
【问题描述】:

我在我的应用程序的一个类中使用 System.Timers.Timer 类。 我知道 Timer 类具有从实现 IDisposable 接口的父 Component 类继承的 Dispose 方法。 下面的类的实例在我的应用程序生命周期中被创建了很多次;它们中的每一个都有一个 Timer 类的实例,该实例在类的生命周期中不断地生成 Elapsed 事件。 我应该在使用 Timer 类来处理计时器对象的类中实现 IDisposable 接口吗? (我见过根本不这样做的代码)。 如果我这样使用下面的类,我担心一些非托管资源不会被释放:

SomeClass someClass = new SomeClass();
someClass.DoSomething();
someClass = null;

班级:

using System.Timers;

public class SomeClass
{
    private Timer m_timer;

    public SomeClass()
    {           
        m_timer = new Timer();
        m_timer.Interval = 1000;
        m_timer.Elapsed += new ElapsedEventHandler(m_timer_Elapsed);
        m_timer.AutoReset = false;
        m_timer.Start();                       
    }

    public void DoSomething()
    {

    }

    private void m_timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            //Do some task
        }
        catch (Exception ex)
        {
            //Ignore
        }
        finally
        {
            if (m_timer != null)
            {
                //Restart the timer
                m_timer.Enabled = true;
            }
        }
    }
}

【问题讨论】:

  • 好问题,目前还没有真正的答案,不幸的是......!

标签: c# .net timer dispose


【解决方案1】:

我看到你在一年前问过这个问题,但让我投入我的 2 美分价值。由于通货膨胀而略少:)。最近我在我们的应用程序中发现我们没有处理计时器。我们有一组对象,每个对象都有一个计时器。当我们从集合中删除该项目时,我们认为它应该被垃圾回收。出于某种原因,计时器并非如此。我们必须在集合中的对象上调用 dispose 以在对象真正被垃圾回收之前摆脱计时器。

【讨论】:

  • 计时器由它在后台创建的 Win32 计时器保持活动状态。计时器上的事件使您的对象保持活动状态。
  • 请注意,System.Timers.Timer 只是包装了对System.Threading.Timer 的调用,并管理一个状态对象(底层 win32 api 使用的回调引用)。
【解决方案2】:

我使用的经验法则是制作任何具有 IDisposable 对象的对象,即 IDisposable 本身(并且仅在显式调用 Dispose 时才释放子对象)

Joe Duffy's blog 上对 IDisposable 进行了很好的讨论,以及看起来与我的优秀 Framework Design Guidelines 书籍副本中的代码示例非常相似的代码示例

【讨论】:

  • 对于任何寻找 Joe Duffy 博客条目的人,web archive link
  • @Korli 已更新链接以指向博客文章的更新版本
  • 谢谢,那个更相关。可悲的是,他的博客标记目前已损坏。至少对我来说。
【解决方案3】:

一般来说,您应该始终处理一次性资源。在您上面概述的情况下,我当然会考虑。如果您在实现计时器的类上实现 IDisposable,则可以在 using 语句中使用该类,这意味着在释放您的类时将显式释放资源。

【讨论】:

    【解决方案4】:

    定时器必须被丢弃,否则它会在你“完成”它之后继续触发一段时间。但是由于线程问题,它可能在你处理它后不久仍然会触发!

    【讨论】:

    • 如果你做一个 timer.Change(Timeout.Infinite, Timeout.Infinite) 怎么办?这会不会停止触发(尽管可能会保持通过事件调用的对象处于活动状态)。
    • @MartinCapodici,在您对“timer.Change”的调用返回之前,它可能仍然“开始”下一次触发。
    • Ian,所以这听起来就像你处置它一样,就另一个可能的解雇而言。不同之处在于,释放它会释放事件持有的内存中的对象,而仅仅停止它不会。
    【解决方案5】:

    我猜定时器对象创建或使用工作线程来触发定时器事件。 dispose 调用将释放线程和与其关联的资源。如果是这种情况,最好调用 dispose,这样您就不会让未使用的线程停留太久。

    【讨论】:

      【解决方案6】:

      通过实现 idisposable,您将能够整理任何也实现了 idisposable 的内部资源,例如您的计时器。

      此外,您还可以更改调用代码以使用 using 语句。

      using (SomeClass someClass = new SomeClass())
      {  
      someClass.DoSomething();  
      }  
      

      【讨论】:

      • 这几乎是一个 nitpik,但为了清楚起见,您需要在 using 语句周围加上括号: using(SomeClass someClass = new SomeClass()) { ... }
      • 非常正确,整天在 C# 和 VB 之间跳来跳去。答案已更新。谢谢
      【解决方案7】:

      我同意罗兰的观点。

      FxCop 中有一条规则可以查找包含 Disposable 对象但未正确实现 IDisposable 的类。

      【讨论】:

        猜你喜欢
        • 2022-11-26
        • 1970-01-01
        • 2022-12-04
        • 1970-01-01
        • 2019-04-25
        • 2021-06-30
        相关资源
        最近更新 更多