形式时未配置定时器

时间:2011-10-31 09:26:48

标签: c# winforms timer dispose

我试图理解为什么Windows.Forms.Timer在创建form时没有被处理掉。我有这个简单的形式:

public partial class Form1 : Form {

    private System.Windows.Forms.Timer timer;

    public Form1() {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {
        timer = new Timer();
        timer.Interval = 1000;
        timer.Tick += new EventHandler(OnTimer);
        timer.Enabled = true;
    }

    private void OnTimer(Object source, EventArgs e) {
        Debug.WriteLine("OnTimer entered");
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
        this.Dispose();
    }
}

当我关闭它时,会调用this.Dispose,但会继续调用计时器触发事件​​。我认为Dispose释放了被处置对象拥有的所有对象。这是不真实的吗? Timer是否有特定行为?

现在,我发现处理计时器的方法是timer.Tick -= OnTimer; - 我在Form1_FormClosed事件中调用它。这是一个好的解决方案,还是我应该这样做?

修改

或者只是做得更好:

private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
    timer.Dispose();
    this.Dispose();
}

5 个答案:

答案 0 :(得分:12)

正如我在之前的评论中告诉你的,你应该尝试:

private Form1_FormClosing(...)
{
    timer.Stop();
    timer.Tick -= new EventHandler(OnTimer);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
{
    timer.Dispose();
    timer = null;   
} 

这很好,因为你阻止计时器再次循环(在FormClosing中)你可以检查其他部分(在这个例子中是非因为你关闭了表单,但是作为例子),如果该对象(计时器)已经< em>删除然后再使用它 所以在其他部分你可以做到

if (timer != null) // Note: this is false if you just use timer.Dispose()
{
    ....
}

答案 1 :(得分:4)

处理IDisposable类的可支配成员的唯一正确方法是在Dispose(bool disposing)方法中执行此操作(查看MSDN文章)。换句话说,您可以打开自动生成的Form.Designer.cs文件并将其放入正确的方法中。

另一方面,如果您通过VS Designer添加Timer(而不是自己实例化),它将被添加到components容器中:

// autogenerated inside Form.Designer.cs, InitializeComponent() method
this.timer = new System.Windows.Forms.Timer(this.components);

然后在components成员被处置时妥善处理:

// autogenerated inside Form.Designer.cs, Dispose(bool disposing) method
if (disposing && (components != null))
{
    components.Dispose();
}

如果您想自己这样做,请记住,如果设计师不认为需要,则不会实例化components。因此,components可能是null

解决此问题的最简单方法:通过从工具箱中拖动计时器来添加计时器,然后在Form_Load处理程序中启动它。

答案 2 :(得分:1)

 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
 {        timer.Stop();    } 

我不应该把这个.Dispose();在表单关闭事件中只是停止计时器。

答案 3 :(得分:1)

EventHandler是持久引用,删除引用并在Closing事件上停止计时器,或者在不需要时立即停止。如果要检查定时器是否处理,请在已关闭的事件

中进行检查

答案 4 :(得分:1)

简单Timer.Dispose()删除计时器资源,包括将来停止计时器。

但是,有可能在Dispose()返回后,有一些回调要么正在执行,要么就位于线程池的工作队列中等待执行。

一旦计时器的所有回调都完成,第二次重载Timer.Dispose(WaitHandle)将发出传入的对象信号。这可以是任何WaitHandle,例如ManualResetEvent

为了简化操作,您可以传入WaitHandle.InvalidHandleTimer.Dispose()只有在所有回调都完成后才会返回。这避免了必须分配一个真正的事件对象,通常是你想要做的。

由于WaitHandle是抽象的,你需要使用一点hack,即创建自己的子类。

class InvalidWaitHandle : WaitHandle {}
Timer tmr = new Timer(...);
tmr.Dispose(new InvalidWaitHandle);