-
Oct 12th, 2012, 11:31 AM
#1
Thread Starter
Lively Member
[VB2008] milisecond
i have a code for stopwatch, but my question is: why does the miliseconds run very slow? here's my code:
Code:
Public Class stopwatch_frm
Dim condition As Boolean = True
Dim miliseconds As Integer = 0
Dim seconds As Integer = 1
Dim minutes As Integer = 1
Private Sub btn_start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_start.Click
Timer1.Enabled = True
End Sub
Private Sub btn_pause_resume_click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_pause_resume.Click
'pause
If condition Then
Timer1.Dispose()
condition = False
btn_pause_resume.Text = "Resume"
Else
'resume
Timer1.Enabled = True
btn_pause_resume.Text = "Pause"
condition = True
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If miliseconds < 10 Then
lbl_milisec.Text = "0" & miliseconds
ElseIf miliseconds < 100 Then
lbl_milisec.Text = miliseconds
Else
lbl_milisec.Text = "00"
If seconds < 10 Then
lbl_sec.Text = "0" & seconds
seconds = seconds + 1
ElseIf seconds < 60 Then
lbl_sec.Text = seconds
seconds = seconds + 1
Else
lbl_sec.Text = "00"
seconds = 1
End If
miliseconds = 0
Exit Sub
End If
miliseconds = miliseconds + 1
End Sub
End Class
here is the design:
-
Oct 12th, 2012, 11:37 AM
#2
Re: [VB2008] milisecond
Timer interval set to 1? The absolute minimum recommended by Microsoft is 35. Most people reckon 50. I wouldn't go below 100 myself.
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Oct 12th, 2012, 11:44 AM
#3
Re: [VB2008] milisecond
I think you forgot to Timer1.Interval which may cause the problem. In the Page Load Set the Timer Interval as
Timer1.Interval=1000
Which will set the tick event to fire every 1 second
Please mark you thread resolved using the Thread Tools as shown
-
Oct 12th, 2012, 11:51 AM
#4
Thread Starter
Lively Member
Re: [VB2008] milisecond
i forgot to say that i set the interval to 10 miliseconds per tick (for miliseconds counter)... and even, when the counter speed seems fail, i set it to 1 milisecond for each tick! and yet it still slow
-
Oct 12th, 2012, 11:58 AM
#5
Re: [VB2008] milisecond
Originally Posted by chipp
i forgot to say that i set the interval to 10 miliseconds per tick (for miliseconds counter)... and even, when the counter speed seems fail, i set it to 1 milisecond for each tick! and yet it still slow
Er yes. That's what I thought. The Timer simply cannot be relied upon at such high frequency. I would go to interval =100 which will give you an accuracy to .1 of a second only but will run at the correct speed.
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Oct 12th, 2012, 12:09 PM
#6
Thread Starter
Lively Member
Re: [VB2008] milisecond
so you mean that it's impossible to using 2 digits miliseconds? i'm wondering, then why MS would allow us to set the interval from 1 - 1000?
-
Oct 12th, 2012, 12:16 PM
#7
Re: [VB2008] milisecond
Where did you get the notion that the setting is 1-1000? I'm not sure if the upper limit is still the same as it was in VB6 but surely it is higher than 1000, I have used values up to 30000 in the past and do not use values below 100
-
Oct 12th, 2012, 12:17 PM
#8
Re: [VB2008] milisecond
I don't know. Perhaps they just like messing with our heads? But from the horse's mouth ...
The Windows Forms Timer component is single-threaded, and is limited to an accuracy of 55 milliseconds. If you require a multithreaded timer with greater accuracy, use the Timer class in the System.Timers namespace.
... it seems they've actually increased the limit since last I looked!
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Oct 12th, 2012, 12:25 PM
#9
Thread Starter
Lively Member
Re: [VB2008] milisecond
I don't know. Perhaps they just like messing with our heads?
my opinion, that it just MS's (another) mistake(s)...
-
Oct 12th, 2012, 12:28 PM
#10
Re: [VB2008] milisecond
I'm pretty sure that the multithreaded timer doesn't get down to 1 millisecond, either.
The interval property on the timer is an Integer, and I believe that the full range of an Integer is allowed, so the top value is WAY above 1000.
My usual boring signature: Nothing
-
Oct 12th, 2012, 12:37 PM
#11
Re: [VB2008] milisecond
I'm not really sure why someone would even want a display done to 10 miliseconds to be updated in real time. It would go so fast that the last digit would just be a blur and even the first one would be hard to read as it would be changing 10 times a second in real time.
-
Oct 12th, 2012, 12:44 PM
#12
Re: [VB2008] milisecond
Apart from the inaccuracies of the Timer, do you realise you are counting in centiseconds, not milliseconds? You are updating the Seconds label after 100 "Ticks". If the timer was capable of raising a Tick event every millisecond, your stopwatch would be running 10 times too fast. Is that why you set the interval to 10? (miliseconds would still be the wrong name for the counter variable, though). The fact that it's running slow just confirms that the Timer Tick is actually occurring at an interval greater than 10 milliseconds. And updating a counter every Tick and then using that counter as a measurement of time just amplifies the inaccuracies.
I'd recommend that you use the StopWatch Class. Create a new StopWatch object, set your Timer interval somewhere between 50 and 100 (or more), and start the StopWatch off when you enable your Timer. Then in your Timer Tick event handler, update your labels with values derived from the StopWatch's Elapsed property (which is a TimeSpan).
Something like:
Code:
Private sw As Stopwatch
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer1.Interval = 75
sw = Stopwatch.StartNew
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
Dim elapsedTime As TimeSpan
elapsedTime = sw.Elapsed
If seconds <> elapsedTime.Seconds Then
seconds = elapsedTime.Seconds
lbl_sec.Text = seconds.ToString("00")
End If
lbl_milisec.Text = elapsedTime.Milliseconds.ToString("000")
End Sub
Last edited by Inferrd; Oct 12th, 2012 at 12:47 PM.
-
Oct 12th, 2012, 02:16 PM
#13
Re: [VB2008] milisecond
Originally Posted by Inferrd
Apart from the inaccuracies of the Timer, do you realise you are counting in centiseconds, not milliseconds? You are updating the Seconds label after 100 "Ticks". If the timer was capable of raising a Tick event every millisecond, your stopwatch would be running 10 times too fast. Is that why you set the interval to 10? (miliseconds would still be the wrong name for the counter variable, though).
Are you just being centipedantic with this?
The stopwatch is an excellent tool for timing things, though, and really is that accurate.
My usual boring signature: Nothing
-
Oct 12th, 2012, 02:31 PM
#14
Re: [VB2008] milisecond
Originally Posted by chipp
my opinion, that it just MS's (another) mistake(s)...
Not at all. That's like saying a pickaxe manufacturer has made a mistake because you can't use their tools to darn a sock. The timer control is designed for a single purpose, regularly repeated actions, with relatively low frequency. Higher frequencies and more accurate timing are perfectly achievable in VB using the appropriate tools and methods.
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Oct 12th, 2012, 06:28 PM
#15
Re: [VB2008] milisecond
I think it would have been reasonable to set the lower limit at something greater than 1, but they may not have known what to set it at. After all, the minimum interval is highly variable. All that happens when the timer ticks is that a message is posted to the queue. If your app is performing a long running operation, the event won't be processed until the process pumps the queue. Therefore, even if you set the interval at 1000, the timer may not tick once a second. In fact, if you do it just right, it won't tick at all.
The timer's nice, and really convenient, but it does have some limitations. I would agree that they could have just made the minimum 50 and been done with it (or even 100), but I think that's pretty minor.
My usual boring signature: Nothing
-
Oct 14th, 2012, 02:52 AM
#16
Re: [VB2008] milisecond
Asking for a timer that's accurate down to 1 ms on a preemptive multi-threaded OS is quite unreasonable. You want anything close to that you might as well write your own OS. That way you could dedicate every processor cycle to executing your code and handling timer interrupts.
[Edit]
Here is an extract from here that shows where timers ultimately derives. Note it says in there that these interrupts are generated every 55ms:-
2) The timer interrupt (int 08h)
I'll assume you've all played old games, back in the days where gameplay and plot were far more important that fancy graphics and nice box-sets... (although these concepts are all important and shouldn't be mutually exclusive one can't help but notice that priorities shifted to uncanny and greedy grounds). Game programmers of the period, often one-man teams with lots of imagination, were sometimes confronted with the problem of implementing certain delays in the game (damn, that enemy plane is closing in too fast... evasive maneuvers... I'll ne...arghhhhhhh). Often, dummy loops of the following form were employed :
for(i=0;i<10000;i++);
This seemed to work. However, this kind of work-around has a significant disadvantage : It relies on processor speed. What a surprise to find out that the powerful hero Kill Them All of our favourite platform game, so deft and gracious on our 20MHZ i386, now, with a 600MHZ Pentium III running a GeForce beast, helplessly dashes against every kind of inoffensive and pitiful obstacle before you even can operate a single key!
Summarizing, we need a way to generate exactly defined time intervals. And what better way than by hardware? Thus, the PC's designers have implemented one (PC/XT and most ATs) or sometimes two (some new ATs or EISA) Programmable Interval Timers (PITs).
The PIT 8253/8254 generates programmable time intervals from an external clock signal of a crystal oscillator that are defined independently from the CPU. It's very flexible and has six modes of operation in all (these modes will not be explained in this tutorial, maybe in a future less generic one).
The 8253/8254 chip comprises three independently and separately programmable counters 0-2, each of which is 16 bits wide. Each counter, or channel, is supplied with its own clock signal (CLK0-CLK2) which serves as the time base for each counter. Each channel is responsible for a different task on the PC :
Channel 0 : This channel is responsible for updating the system clock, generating interrupts every 55ms (approximately). This is about once every 1/18.2 seconds. Sometimes this is called the "eighteenth second clock" but we will refer to it as the timer interrupt. We'll discuss this channel in more detail in a little while.
Channel 1 : This channel controls DMA memory refreshing, instructing all 18 CLK cycles on a DMA chip to carry out a dummy read cycle. In the course of this dummy cycle, data is read from memory onto the data bus and the address buffers, and address decoders and sense amplifiers in the memory chips are activated to refresh one memory cell row. But the data is not read by any peripheral. Instead, it's discarded in the next bus cycle. This is done because DRAM's memory cells must be periodically refreshed or they quickly lose their charge. One interesting thing that should be noted is that most system designers lay out the memory refresh rather carefully, that is, the memory is refreshed more often that is really necessary. This so-called refresh overhead can reach 10% or more. Reprogramming channel 1 to refresh memory at a slower rate can sometimes speed up system performance, but don't overdue it or data losses might incur (giving rise to parity errors upon reading main memory).
Channel 2 : This channel is dedicated to the tone frequency generation for the installed speaker. It's normally programmed to generate a square wave so a continuous tone is heard. Reprogramming it for "Interrupt on Terminal Count" mode is a nifty trick which can be used to play 8-bit samples from the PC speaker. You may generate various frequencies with it. The audible range of tones lies between about 16Hz and 16kHz. Frequencies above and below this range are called infra- or supersonic: Your Pc's amplifier is probably unable to generate such tones.
The timer interrupt vector (channel 0) is probably the most commonly patched interrupt in the system. However, it turns out there are two of these vectors in the system. The first one, int 08h, is the hardware vector associated with the timer interrupt. Unless you're willing to taunt fate, it's not a good idea to patch this interrupt. If you want to build a timer handler, go for the second interrupt, interrupt 1ch. The BIOS' timer ISR (int 08h) always executes an int 1ch instruction before it returns. Catching it, assuming control and chain back to the old ISR is the best way to design your timer handler. Unless you're willing to duplicate the BIOS and DOS timer code, you should never completely replace the existing timer ISR with one of your own. Twiddling with int 1ch can be very dangerous and misuse can cause your system to crash or otherwise malfunction.
Finally, without entering into too much detail, I'll leave you with the port addresses of the various 8253/8254 PIT registers (the control register loads the counters and controls the various operation modes) :
Last edited by Niya; Oct 14th, 2012 at 03:35 AM.
-
Oct 14th, 2012, 03:09 AM
#17
Re: [VB2008] milisecond
I forgot to mention though that Windows does have a multimedia timer that is purported to be accurate to 1ms. Code that demonstrates using them in a .Net language is a little difficult to come by though.
-
Oct 14th, 2012, 09:20 AM
#18
Re: [VB2008] milisecond
All well and good but as this is a stopwatch, it would seem logical to simply use the Stopwatch object for timing and relegate the Timer to display only. You only need to display tenths when the watch is running because anything else is simply unreadable anyway. When the watch is stopped you can display the time elapsed up to 7 decimal places (or should that be down to?) should you feel the need!
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Oct 14th, 2012, 09:49 AM
#19
Thread Starter
Lively Member
Re: [VB2008] milisecond
btw, from my side (haven't read all the replies), i'll just use 1 digit of miliseconds, just like dunfiddin suggest
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|