tags:

views:

117

answers:

4

My c# WinForm application uses the Elapsed event of a System.Timers.Timer to open a new form. It was pointed out to me (in an earlier question I posted on a different topic) that this was a bad idea; it was suggested I use System.Windows.Forms.Timer.

I've changed my code in response to this suggestion and my application appears to work; however, I'm still rather low on the WinForms learning curve and I'd enjoy feedback on whether or not I've correctly changed my code. (I'm concerned because the old way--the bad way--also appeared to work.)

I have two forms: frmTimer and frmUser. Each form resides in a separate project in the WinForms solution. FrmTimer uses the namespace 'svchostx' and runs from svchostx.exe. FrmUser uses the namespace 'XXXUser' and runs from XXXUser.exe (where XXX is the application's name).

Is it bad to use System.Timers.Timer in this context and, if it is, then have I made the correct changes?

In frmTimer this code:

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) {

Was replaced with this code:

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) {

In both the old code and the new code, the timer event checks to see if certain conditions are meet, and when they're meet, then frmUser is opened. FrmUser shows a quiz screen (with math or spelling questions) that the user answers. FrmTimer is never seen and contains only logic to determine when frmUser is opened.

Also, Visual Studio's IntelliSense says this about System.Windows.Forms.Timer: "This timer is optimized for use in Windows Forms applications and must be used in a window." The last part of that sentence confuses me because frmTimer doesn't really have a window (the form is never seen). I'm not sure what is meant by 'must be used in a window'--yes, I am pretty low on the learning curve.

Any advice or help here is appreciated.

+1  A: 

Use System.Windows.Forms.Timer for interaction with WinForms.
System.Timers.Timer is built for other purposes, like background operations and services, and its not synchronized with UI Threads.

Have also a look here.

serhio
Hello Serhio, thank you for answering. I read the link you suggested the other day but, sadly, I do not understand the descriptions in the 'Feature description' column on the left hand side of the table.
Frederick
+1  A: 

Read about the three types of timers available in .net from here. There is really nothing wrong with using the System.Windows.Forms.Timer for UI programming.

Marcel Gheorghita
Thank you Marcel, the document you linked to has the most understandable description of the three timer classes that I have read. The document mentions that when the UI thread sleeps the System.Windows.Forms.Timer will skip the timer events while the System.Timers.Timer won't. My question is, if my frmTimer is open and the computer goes into sleep mode or standby mode, does this cause the UI thread to sleep? Or is UI thread sleeping something different? I ask because I don't want my timer event to fire many times after the computer wakes up from standby mode.
Frederick
+4  A: 

The way you are using the System.Timers.Timer is correct. The key to making this timer work in UI scenarios is the SynchronizingObject property. When set to null this timer raises the Elapsed event on a ThreadPool thread. When set to an instance of an ISynchronizeInvoke object it raises the event on the thread hosting that object. If that ISynchronizeInvoke instance is none other than a control or form then the hosting thread is the thread that the control or form was created on...the main UI thread.

The System.Windows.Forms.Timer can only be used in UI scenarios because it creates a window handle. You do not actually see this window get created, but it is there. And of course this timer always raises its Tick event on the UI thread.

Brian Gideon
Brian, thanks for responding, great answer. Although, are you saying that both ways are valid and safe? Are you saying that it is ok to use System.Timers.Timer to open a new form because I also have included 'this.tmTimer.SynchronizingObject = this;'?
Frederick
@Frederick: That is exactly what I am saying. But to be fair to Hans in the other question you cited; he probably did not know that you had set the `SynchronizingObject` property.
Brian Gideon
@Brian, yes, I posted this question for the very reason that Hans had seen only a small part of my code and it would have been off-topic to have followed-up on his comment in my other question.
Frederick
@Brian, lastly, between the two versions of code shown here in this question (System.Timers.Timer and System.Windows.Forms.Timer), is one better than the other for my intended use?
Frederick
@Frederick: I am not sure it really matters. For what it is worth the `System.Timers.Timer` actually uses `System.Threading.Timer` behind the scenes.
Brian Gideon
A: 

If two windows are created in the same thread, then anything which stalls the UI thread for one will stall it for both. On the other hand, controls from one window can freely manipulate the other window without requiring any explicit synchronization. If you use a forms.Timer, your new window can only be created when the UI is idle; unless you endeavor to make it otherwise, your new form will use the same thread as the one with the timer. If you use another type of timer, your new form can appear even when all other UI threads are busy; the new form will not share a thread with other forms. Note that since the form's thread won't die until the form is closed, it may be better to create a new thread (from the timer event) than hog a thread-pool thread.

supercat