使用System.Timers.Timer打开一个新窗体有多糟糕?

我的c#WinForm应用程序使用System.Timers.Timer的Elapsed事件来打开一个新的窗体。 有人向我指出(在较早的问题上,我发表了一个不同的话题),这是一个坏主意。 有人build议我使用System.Windows.Forms.Timer。

我已经改变了我的代码,以回应这个build议,我的应用程序似乎工作; 不过,在WinForms的学习曲线上,我还是比较低调,我很乐意反馈我是否正确地更改了我的代码。 (我担心,因为旧的方式 – 坏的方式 – 也似乎工作。)

我有两种forms:frmTimer和frmUser。 每个窗体都驻留在WinForms解决scheme的一个单独的项目中。 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显示用户回答的测验屏幕(包含math或拼写问题)。 FrmTimer从不被看到,只包含逻辑来确定frmUser何时被打开。

此外,Visual Studio的智能感知说这关于System.Windows.Forms.Timer:“此计时器是优化用于Windows窗体应用程序,必须在窗口中使用”。 这句话的最后一部分让我感到困惑,因为frmTimer没有真正的窗口(窗体从未见过)。 我不确定“必须在窗口中使用”是什么意思 – 是的,我的学习曲线很低。

任何意见或帮助在这里表示赞赏。

你使用System.Timers.Timer是正确的。 在UI场景中使此计时器工作的关键是SynchronizingObject属性。 当设置为null此计时器引发ThreadPool线程上的Elapsed事件。 当设置为ISynchronizeInvoke对象的实例时,它会引发宿主该对象的线程上的事件。 如果该ISynchronizeInvoke实例是一个控件或窗体,那么宿主线程就是在主UI线程上创建控件或窗体的线程。

System.Windows.Forms.Timer只能在UI场景中使用,因为它创建了一个窗口句柄。 你实际上并没有看到这个窗口被创建,但它在那里。 当然,这个计时器总是在UI线程上引发它的Tick事件。

使用System.Windows.Forms.Timer与WinForms进行交互。
System.Timers.Timer是为了其他目的而构建的,比如后台操作和服务,并且不与UI线程同步。

也看看这里 。

从这里阅读.net中的三种类型的定时器。 使用System.Windows.Forms.Timer进行UI编程确实没有什么问题。

如果两个窗口是在同一个线程中创建的,那么将UI线程挂起的任何东西都会使它停滞。 另一方面,来自一个窗口的控制可以自由地操作另一个窗口而不需要任何明确的同步。 如果使用forms.Timer,则只能在UI空闲时创建新窗口; 除非你努力去做,否则你的新表单将使用与定时器相同的线程。 如果您使用其他类型的计时器,则即使所有其他UI线程都处于忙碌状态,您的新表单也会出现; 新表单将不会与其他表单共享一个线程。 请注意,因为表单的线程在表单关闭之前不会死亡,所以最好从一个线程池线程创建一个新的线程(来自timer事件)。