EDN Admin
Well-known member
I like little timers. Ive used them a lot in VB6. So today when somebody posted a question about making a button blink I figured it would be a nice way to start the morning. Something simple. Six hours later I know less now
than I KNEW then. Aint life grand!
That thread evolved away from timers and into a (probably more usefull) discussion of user interfaces so I thought Id put my comments in this new thread (that is a double entendre as we shall soon see).
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/9b3ff3d4-f137-44f4-9f03-d5f7fff6e36a http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/9b3ff3d4-f137-44f4-9f03-d5f7fff6e36a
If any of this is wrong PLEASE correct me.
There are three timers available in Visual Basic 2010.
<ol>
System.Timers.TimerSystem.Threading.TimerSystem.Windows.Forms.Timer</ol>
However, we are really not that well endowed with timers. I ran into this over on a C# page:
>>The funny thing is System.Timers.Timer uses System.Threading.Timer internally (can be found through Reflector). So its a wrapper around Threading.Timer and microsoft tried to do some fancy things .......... So its advised to use Threading.Timer.
<<
Reflection is somewhere beyond the end of my diving board right now. If anyone can verify or refute that statement, please post. Im going to take that comment on face value for now and drop System.Timers.Timer from my list.
Microsoft (in VB help) says about System.Threading.Timer:<span><span class="x_selflink >>System.Threading<span id="x_ID0EBAFAAAABFAAAAA .Timer
is a simple, lightweight timer that uses callback methods and is served by thread pool threads. It is not recommended for use with Windows Forms, because its callbacks do not occur on the user interface thread.<<
So, when you use a System.Threading.Timer to do something from a form you immediately end up with three threads. The first is the thread that the form is using. The second is the thread that the timer is using. The third is the thread that
the callback routine is using. At the end of all that you are not on the correct thread to actually do anything to the form. You would have to feed the callback routine a delegate that runs on the form thread to get back to where you can actually
change the color of a font without running into possible problems (sounds like a Fancy Thing to me).
If you dont get it all right you end up with random trouble like this thread:
http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/b179fd77-c352-4c32-ab97-30ee38c525ef http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/b179fd77-c352-4c32-ab97-30ee38c525ef
Ive had those kind of random problems today trying to use the Threading.Timer. So unless you want to run routines totally in the background, it is hard to see how three threads and two delegate calls is going to get a better timer than the Forms.Timer.
Yes, the Forms.Timer is probably a wrapper too but at some point you HAVE TO TRUST SOMEBODY to write some decent code. Again, anybody who knows Reflection could probably look and see if the Forms.Timer is, also, a wrapper around the Threading.Timer.
I wouldnt be a bit surprised.
So I am left (for most things at least) with the Windows.System.Forms.TImer. Of course this is the one you get from the Toolbox in design mode. A lot of places say that the accuracy is around 15ms. MS says 55ms. I think it is always
long and never short but have not tested that yet (sun comes up again tomorrow).
Earlier I found out that the .Net Forms.Timer does not work the same as the VB6 Forms.Timer I am used to using. The VB6 timer suspends time during the execution of the code path between timer entry and timer exit. Thus the time Interval is
from exit of the timer on one pass to entry of the timer on the next pass. The .Net timer does not suspend time. So the time Interval is from one timer enty to the next timer entry.
This results in a situation for the .Net forms timer where you can have multiple calls open at one time. This happens when the code path initiated by the timer takes longer than the timer interval. This results in the stack growing and maybe
other problems?
Note - I am not saying one way is better than the other. Just that they are different. The .Net way gives a better metronome type of timing. The VB6 way gives you only one open timer code path. So the final task of the day was to
figure out a way to replicate the VB6 timer using the .Net timer.
The first thing I tried was to turn the timer off as the first line of code and then turn it back on as the last line of code (you know it is on at entry or it would not have been called). But this logic has a pretty big bug in it. What if I
try to turn the timer off during the execution of the timer code path? I lose that try. Whoops, my bad and therefore the Enabled flag is off limits.
The best way I could think of is to grab and keep the current Interval on timer entry, set the interval to some large number to keep the timer from firing (I used the maximum integer), and reset the Interval just before timer exit if the Interval was not
reset during the execution of the code path. Yes there is still a bug. This bug occurs if I actually sets the timer Interval to Int32.MaxValue during the execution of the code path. Oh well, one more thing to remember.
So the code to simulate the VB6 timer looks like this:
<pre class="prettyprint lang-vb Private Sub Timer3_Tick(sender As System.Object, e As System.EventArgs) Handles Timer3.Tick
Dim holdInterval As Integer = Timer3.Interval
Timer3.Interval = Int32.MaxValue
Do/Call the code path you want to initiate here
If Timer3.Interval = Int32.MaxValue Then
Timer3.Interval = holdInterval
End If
End Sub[/code]
<br/>
View the full article
than I KNEW then. Aint life grand!
That thread evolved away from timers and into a (probably more usefull) discussion of user interfaces so I thought Id put my comments in this new thread (that is a double entendre as we shall soon see).
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/9b3ff3d4-f137-44f4-9f03-d5f7fff6e36a http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/9b3ff3d4-f137-44f4-9f03-d5f7fff6e36a
If any of this is wrong PLEASE correct me.
There are three timers available in Visual Basic 2010.
<ol>
System.Timers.TimerSystem.Threading.TimerSystem.Windows.Forms.Timer</ol>
However, we are really not that well endowed with timers. I ran into this over on a C# page:
>>The funny thing is System.Timers.Timer uses System.Threading.Timer internally (can be found through Reflector). So its a wrapper around Threading.Timer and microsoft tried to do some fancy things .......... So its advised to use Threading.Timer.
<<
Reflection is somewhere beyond the end of my diving board right now. If anyone can verify or refute that statement, please post. Im going to take that comment on face value for now and drop System.Timers.Timer from my list.
Microsoft (in VB help) says about System.Threading.Timer:<span><span class="x_selflink >>System.Threading<span id="x_ID0EBAFAAAABFAAAAA .Timer
is a simple, lightweight timer that uses callback methods and is served by thread pool threads. It is not recommended for use with Windows Forms, because its callbacks do not occur on the user interface thread.<<
So, when you use a System.Threading.Timer to do something from a form you immediately end up with three threads. The first is the thread that the form is using. The second is the thread that the timer is using. The third is the thread that
the callback routine is using. At the end of all that you are not on the correct thread to actually do anything to the form. You would have to feed the callback routine a delegate that runs on the form thread to get back to where you can actually
change the color of a font without running into possible problems (sounds like a Fancy Thing to me).
If you dont get it all right you end up with random trouble like this thread:
http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/b179fd77-c352-4c32-ab97-30ee38c525ef http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/b179fd77-c352-4c32-ab97-30ee38c525ef
Ive had those kind of random problems today trying to use the Threading.Timer. So unless you want to run routines totally in the background, it is hard to see how three threads and two delegate calls is going to get a better timer than the Forms.Timer.
Yes, the Forms.Timer is probably a wrapper too but at some point you HAVE TO TRUST SOMEBODY to write some decent code. Again, anybody who knows Reflection could probably look and see if the Forms.Timer is, also, a wrapper around the Threading.Timer.
I wouldnt be a bit surprised.
So I am left (for most things at least) with the Windows.System.Forms.TImer. Of course this is the one you get from the Toolbox in design mode. A lot of places say that the accuracy is around 15ms. MS says 55ms. I think it is always
long and never short but have not tested that yet (sun comes up again tomorrow).
Earlier I found out that the .Net Forms.Timer does not work the same as the VB6 Forms.Timer I am used to using. The VB6 timer suspends time during the execution of the code path between timer entry and timer exit. Thus the time Interval is
from exit of the timer on one pass to entry of the timer on the next pass. The .Net timer does not suspend time. So the time Interval is from one timer enty to the next timer entry.
This results in a situation for the .Net forms timer where you can have multiple calls open at one time. This happens when the code path initiated by the timer takes longer than the timer interval. This results in the stack growing and maybe
other problems?
Note - I am not saying one way is better than the other. Just that they are different. The .Net way gives a better metronome type of timing. The VB6 way gives you only one open timer code path. So the final task of the day was to
figure out a way to replicate the VB6 timer using the .Net timer.
The first thing I tried was to turn the timer off as the first line of code and then turn it back on as the last line of code (you know it is on at entry or it would not have been called). But this logic has a pretty big bug in it. What if I
try to turn the timer off during the execution of the timer code path? I lose that try. Whoops, my bad and therefore the Enabled flag is off limits.
The best way I could think of is to grab and keep the current Interval on timer entry, set the interval to some large number to keep the timer from firing (I used the maximum integer), and reset the Interval just before timer exit if the Interval was not
reset during the execution of the code path. Yes there is still a bug. This bug occurs if I actually sets the timer Interval to Int32.MaxValue during the execution of the code path. Oh well, one more thing to remember.
So the code to simulate the VB6 timer looks like this:
<pre class="prettyprint lang-vb Private Sub Timer3_Tick(sender As System.Object, e As System.EventArgs) Handles Timer3.Tick
Dim holdInterval As Integer = Timer3.Interval
Timer3.Interval = Int32.MaxValue
Do/Call the code path you want to initiate here
If Timer3.Interval = Int32.MaxValue Then
Timer3.Interval = holdInterval
End If
End Sub[/code]
<br/>
View the full article