System.Timers.Timer and InvokeRequired

M

Michael C#

Hi all,

I set up a System.Timers.Time in my app. The code basically just updates
the screen, but since the processing performed is so CPU-intensive, I wanted
to make sure it gets updated regularly; like every 1.5 secs. or so. I only
ran into one issue - the MyTimer_Elapsed event handler was not updating the
screen correctly all the time, often leaving large chunks of the screen
un-painted for several seconds.

On a whim I decided to check the InvokeRequired property of my form in the
Event Handler... and whaddyaknow, it was True. So now I've added the proper
code to check InvokeRequired and to update the screen using Invoke(), but I
hadn't realized I needed to use Invoke to update the screen from within the
System.Timers.Timer? Even in the sample MSDN code for the
System.Timers.Timer they leave out the Invoke(); i.e.:

Private Sub myTimer_Elapsed(ByVal sender As System.Object, ByVal e As
System.Timers.ElapsedEventArgs)
System.Windows.Forms.MessageBox.Show("Elapsed!", _
"Timer Event Raised!")
End Sub

While I know that Invoke() must be called to update the UI from worker
threads, outside of that is its usage more or less a matter of trial and
error? Or are there additional rules that should be followed when
determining when to use Invoke()?

Just wondering. Thanks.
 
B

Bob Powell [MVP]

The System.Timers.Timer runs on a different thread to the main UI of the
application. Even though the code for the timer service might be in your
form, the thread it's called on will be different and therefore you'll need
to check to see if other methods in your form or class should be called
using invoke.

Generally, you should know whether you're using threads either explicitly or
implicitly as in the case of System.Timers.Timer and code for those
circumstances. Unfortunately the only way to know this is to read the fine
print in the docs.

Don't cite MSDN as a shining example. It's full to bursting with
horribleness. See if you can find an example of Dispose being used on a
Graphic object in there...

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
T

Tom Shelton

Hi all,

I set up a System.Timers.Time in my app. The code basically just updates
the screen, but since the processing performed is so CPU-intensive, I wanted
to make sure it gets updated regularly; like every 1.5 secs. or so. I only
ran into one issue - the MyTimer_Elapsed event handler was not updating the
screen correctly all the time, often leaving large chunks of the screen
un-painted for several seconds.

On a whim I decided to check the InvokeRequired property of my form in the
Event Handler... and whaddyaknow, it was True. So now I've added the proper
code to check InvokeRequired and to update the screen using Invoke(), but I
hadn't realized I needed to use Invoke to update the screen from within the
System.Timers.Timer? Even in the sample MSDN code for the
System.Timers.Timer they leave out the Invoke(); i.e.:

Private Sub myTimer_Elapsed(ByVal sender As System.Object, ByVal e As
System.Timers.ElapsedEventArgs)
System.Windows.Forms.MessageBox.Show("Elapsed!", _
"Timer Event Raised!")
End Sub

While I know that Invoke() must be called to update the UI from worker
threads, outside of that is its usage more or less a matter of trial and
error? Or are there additional rules that should be followed when
determining when to use Invoke()?

Just wondering. Thanks.

The rule is that if the procedure that is updating your UI is on another
thread, you must use invoke to marshal back to that thread. This is
necessary with System.Timers because all the calls happen on a
ThreadPool thread.

That said, the System.Timer.Timer component has the ability to
automatically marshal calls to a specific object via the SyncronizingObject
property. If you add the component from the components dialog in the
ide to a form, it should automatically set this to the form. If you
creat the object in code - then this will be null (nothing in vb) and
you have the problem you mentioned. So, if you create it in code, you
could always set it to the form you want to update it manully - before
you start it ticking :)
 
M

Michael C#

Thanks for the info. While we're on the topic, is it ok to assume that
Invoke needs to be called for *all* UI objects at a given point in time if
InvokeRequired is True for the Form itself? In a lot of code I've seen, for
some reason the authors feel the need to check InvokeRequired for each and
every object they're updating on the UI; every text box, each label, all
progress bars, etc. It seems that if the form itself needs to be Invoked,
then all of the controls it contains would need to be Invoked. Is this a
safe assumption? Or is there a special reason to call InvokeRequired
multiple times for each individual control?

Thanks again
 
T

Tom Shelton

Thanks for the info. While we're on the topic, is it ok to assume that
Invoke needs to be called for *all* UI objects at a given point in time if
InvokeRequired is True for the Form itself? In a lot of code I've seen, for
some reason the authors feel the need to check InvokeRequired for each and
every object they're updating on the UI; every text box, each label, all
progress bars, etc. It seems that if the form itself needs to be Invoked,
then all of the controls it contains would need to be Invoked. Is this a
safe assumption? Or is there a special reason to call InvokeRequired
multiple times for each individual control?

Thanks again

I only check the form... I see no need to check all it's child
controls, since they are going to be on the same thread as the form.
So, basically, if the form returns true for InvokeRequired, all it's
contained controls are going to as well.
 
B

Bob Powell [MVP]

Most applications will be single threaded and so one can assume that
checking InvokeRequired is not necessary. Threaded UI updates are not
recommended but they are possible but any developer using them needs to be
aware of the problems they can cause and techniques to keep the app running
sweetly.

The rule of thumb is one thread means no need to bother with InvokeRequired
ever. More than one thread means that you ALWAYS check from the non-UI
threads.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top