我有各种小型C#winforms应用程序(虽然这应该同样适用于任何.NET应用程序),这些应用程序在关闭时需要执行一些小任务。
我一直在利用.FormClosing
事件做一些事情,比如编写当前设置文件并等待后台线程完成等等。
就最佳实践而言,有两个问题浮现在脑海中:
关闭表单时是否需要停止计时器(或类似任务)?知道终止应用程序应该处理计时器,在表单结束时发出timer.Stop()
是个好主意吗?是否有可能一旦进入.FormClosing
方法,计时器可能再次触发?
最后一分钟的任务(例如撰写设置文件)应该在.FormClosing
或.FormClosed
事件(或其他地方)以及为什么?
很抱歉将这些问题结合起来,但我觉得它们的关系非常密切,可以保证关于正确关闭基于表单的应用程序的单个帖子。
答案 0 :(得分:4)
保证单线程
嗯,你已经回答了自己的问题:) FormClosing和计时器的Tick事件等事件都在一个线程上运行。没有办法让计时器“破解”到一个线程并运行Tick事件,你的线程正在忙于清理工作。 Tick事件在完成运行事件处理程序并重新进入消息循环后再次进入空闲状态时才会运行。
但在此之前,表单将自行销毁,处理其所有控件和组件。这结束了计时器的Tick事件运行的任何机会。没有必要明确地停止()它。
对于System.Timers.Timer或其他异步组件(如BackgroundWorker),情况并非如此。在表单关闭之前停止这些是非常重要。如果你不这样做,你的代码通常会在ObjectDisposedException上炸弹。特别是System.Timers.Timer 非常很难停止,它可以在用户关闭表单之前调度调用Elapsed事件处理程序的线程一微秒。发生这种情况时,大Kaboom。不要使用它。
答案 1 :(得分:3)
我应该停止计时器吗?
不是真的,但也不会受伤。
FormClosing后是否可以触发Timer?
棘手。通常情况下,但如果Closing链中的某些代码调用Application.DoEvents(),我不会排除它。总是一个好主意,以防御性方式编程你的Timer-handler。
最后一分钟的任务应该在.FormClosing还是.FormClosed?
FormClosing是有条件的,它的主要功能是显示“先保存?”盒子或类似的。我会把所有东西放在FormClosed中,除非它确实需要更早(即它需要其他组件/控件生存和活动)。