forms时未配置定时器
我试图理解为什么在创建它的form
时不会处理Windows.Forms.Timer
。 我有这个简单的forms:
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
释放了被Dispose
对象拥有的所有对象。 这是不真实的吗? Timer
有特定的行为吗?
现在,我发现处理计时器的方法是做timer.Tick -= OnTimer;
– 我在Form1_FormClosed
事件中调用它。 这是一个好的解决方案,还是我应该这样做?
编辑
或者它是否更好:
private void Form1_FormClosed(object sender, FormClosedEventArgs e) { timer.Dispose(); this.Dispose(); }
?
正如我在之前的评论中告诉你的,你应该尝试:
private Form1_FormClosing(...) { timer.Stop(); timer.Tick -= new EventHandler(OnTimer); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { timer.Dispose(); timer = null; }
这很好,因为你阻止计时器再次循环(在FormClosing中)你可以检查其他部分(在这个例子中是非因为你正在关闭表单,但是作为例子)如果在使用它之前删除了该对象(计时器) 。
所以在其他部分你可以做到
if (timer != null) // Note: this is false if you just use timer.Dispose() { .... }
处理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
处理程序中启动它。
private void Form1_FormClosed(object sender, FormClosedEventArgs e) { timer.Stop(); }
我不应该把这个.Dispose(); 在表单关闭事件只是停止计时器。
EventHandler是持久引用,删除引用并在结束事件上或在不需要时立即停止计时器。 如果要检查定时器是否处理,请在已关闭事件中进行检查
简单的Timer.Dispose()
删除计时器资源,包括将来停止计时器。
但是,在Dispose()
返回之后,有可能是主动执行或坐在线程池的工作队列中等待执行的回调。
第二次重载,一旦定时器的所有回调都完成, Timer.Dispose(WaitHandle)
将发出传入的对象信号。 这可以是任何WaitHandle
,例如ManualResetEvent
。
为了简化操作,您可以传入WaitHandle.InvalidHandle
并且Timer.Dispose()
仅在所有回调都已完成时返回。 这避免了必须分配一个真正的事件对象,通常是你想要做的。
由于WaitHandle
是抽象的,你需要使用一点hack,即创建自己的子类。
class InvalidWaitHandle : WaitHandle {} Timer tmr = new Timer(...); tmr.Dispose(new InvalidWaitHandle);