我的c#WinForm应用程序使用System.Timers.Timer的Elapsed事件打开一个新表单。有人向我指出(在我之前的question我发表了一个不同的主题)这是一个坏主意;有人建议我使用System.Windows.Forms.Timer。
我已根据此建议更改了我的代码,我的应用程序似乎正常工作;但是,我在WinForms学习曲线上仍然相当低,我会喜欢有关我是否正确更改代码的反馈。 (我很担心,因为旧方式 - 不好的方式 - 似乎也有效。)
我有两种形式:frmTimer和frmUser。每个表单都驻留在WinForms解决方案中的单独项目中。 FrmTimer使用命名空间'svchostx'并从svchostx.exe运行。 FrmUser使用命名空间“XXXUser”并从XXXUser.exe运行(其中XXX是应用程序的名称)。
在此上下文中使用System.Timers.Timer是否不好,如果是,那么我是否进行了正确的更改?
在frmTimer中这段代码:
this.tmTimer= new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.tmTimer)).BeginInit();
//
// tmTimer
//
this.tmTimer.Interval = 20000;
this.tmTimer.SynchronizingObject = this;
this.tmTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.tmTimer_Elapsed);
private System.Timers.Timer tmTimer;
private void tmTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
替换为此代码:
this.timer1 = new System.Windows.Forms.Timer(this.components);
//
// timer1
//
this.timer1.Interval = 20000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
private System.Windows.Forms.Timer timer1;
private void timer1_Tick(object sender, System.EventArgs e) {
在旧代码和新代码中,计时器事件检查是否满足某些条件,当它们满足时,则打开frmUser。 FrmUser显示用户回答的测验屏幕(带有数学或拼写问题)。 FrmTimer从未见过,只包含确定frmUser何时打开的逻辑。
此外,Visual Studio的IntelliSense对System.Windows.Forms.Timer说:“此计时器已针对Windows窗体应用程序进行了优化,必须在窗口中使用。”这句话的最后一部分让我感到困惑,因为frmTimer实际上没有窗口(表格从未见过)。我不确定'必须在窗口中使用'是什么意思 - 是的,我的学习曲线非常低。
欢迎任何建议或帮助。
答案 0 :(得分:4)
您使用System.Timers.Timer
的方式是正确的。使此计时器在UI方案中工作的关键是SynchronizingObject
属性。设置为null
时,此计时器会在Elapsed
线程上引发ThreadPool
事件。当设置为ISynchronizeInvoke
对象的实例时,它会在托管该对象的线程上引发事件。如果ISynchronizeInvoke
实例只是一个控件或表单,那么托管线程就是在主UI线程上创建控件或表单的线程。
System.Windows.Forms.Timer
只能在UI场景中使用,因为它会创建一个窗口句柄。你实际上并没有看到这个窗口被创建,但它就在那里。当然,这个计时器总是在UI线程上引发它的Tick
事件。
答案 1 :(得分:1)
使用System.Windows.Forms.Timer
与WinForms进行互动
System.Timers.Timer
是为其他目的而构建的,例如后台操作和服务,并且它与UI线程不同步。
还要看here。
答案 2 :(得分:1)
从here了解.net中可用的三种定时器。使用System.Windows.Forms.Timer
进行UI编程确实没有错。
答案 3 :(得分:0)
如果在同一个线程中创建了两个窗口,那么任何将UI线程停在一个窗口的窗口都将使两个窗口都停止。另一方面,来自一个窗口的控件可以自由地操纵另一个窗口,而不需要任何显式同步。如果使用forms.Timer,则只能在UI空闲时创建新窗口;除非你努力做到这一点,否则你的新表格将使用与计时器相同的线程。如果您使用其他类型的计时器,即使所有其他UI线程都忙,您的新表单也会出现;新表单不会与其他表单共享一个帖子。请注意,由于表单的线程在表单关闭之前不会消失,因此最好创建一个新线程(来自timer事件),而不是占用线程池线程。