Results 1 to 22 of 22

Thread: Too fast for VB to detect? Stopwatch.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Oct 2009
    Posts
    27

    Too fast for VB to detect? Stopwatch.

    Hi,

    I put

    Label1.Text = Watch.Elapsed.Milliseconds
    And notice that it goes from 0 to 1000 milliseconds and then back to 0 starting over every time.
    Ok, no problems

    Then I do some tests and put,

    If e key pressed = True Then
    Count = Watch.Elapsed.Milliseconds
    label2.text=count
    End If
    Whenever I press e, it logs the value in count and displays it.
    No problems.

    Now if i do this,

    If Watch.Elapsed.Milliseconds = 5 (or any number from 0 - 1000) Then
    End
    End If
    This should end program once it hits 5 milliseconds.
    But the problem is it doesn't.

    On one of my test runs i notice it does end, but only after a little while. Does this mean VB has a hard time detecting the stopwatch or something?

    How can i fix this?
    (I am beginner so please, not too technical or vague.)

    BTW: Windows XP Pro 64bit,
    VB.NET 2010 Express

  2. #2
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    The following code does two things. It automatically closes the program after some period of time, and times the interval between Button1 clicks. You will need a form with a label and button to see the code work.

    Code:
    Public Class Form1
    
        Dim stpw As New Stopwatch
        Dim tmr As New Windows.Forms.Timer
    
        Private Sub Form1_Shown(ByVal sender As Object, _
                                ByVal e As System.EventArgs) Handles Me.Shown
            AddHandler tmr.Tick, AddressOf tmr_Tick 'add handler for timer
            tmr.Interval = 100 'set how often (in ms.) to check
            tmr.Start() 'start the timer
            stpw.Reset() 'start the stopwatch
            stpw.Start()
        End Sub
    
        Dim stopIn As New TimeSpan(0, 0, 30) '30 seconds  (hours,minutes,seconds)
    
        Private Sub tmr_Tick(ByVal sender As System.Object, _
                             ByVal e As System.EventArgs)
            'close program in stopIN seconds
            If stpw.Elapsed > stopIn Then Me.Close()
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) Handles Button1.Click
            Static lastTS As New TimeSpan
            If lastTS.TotalMilliseconds = 0 Then 'first time
                lastTS = stpw.Elapsed
                Exit Sub
            End If
            'display time between button clicks
            Dim curElapsed As TimeSpan = stpw.Elapsed
            Label1.Text = (curElapsed - lastTS).ToString
            lastTS = curElapsed
        End Sub
    End Class
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  3. #3
    New Member GinGin's Avatar
    Join Date
    Oct 2010
    Posts
    13

    Re: Too fast for VB to detect? Stopwatch.

    I'm afraid the StopWatch control simply isn't accurate enough for whatever it is you're trying to achieve. If you simply want to see when a certain amount of time has passed, you could do it using a thread.

    vb Code:
    1. Dim i As UInt32 = 0
    2.         While (i < 5)
    3.             Threading.Thread.Sleep(1)
    4.         End While
    5.         '5 ms passed

    Or alternatively replacing
    vb Code:
    1. If Watch.Elapsed.Milliseconds = 5
    in your code with
    vb Code:
    1. If Watch.Elapsed.Milliseconds >= 5
    in which case it would fire if the elapsed milliseconds are either 5, or bigger than 5.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Too fast for VB to detect? Stopwatch.

    Ya. The problem is that you are checking for exactly 5 milliseconds. That means that it will only be true if the the count is 5 at the exact instant that the condition is tested. Not a very likely scenario.

    However, it does bring up the question as to what you are trying to achieve. Are you just playing around with the stopwatch, or is there some ultimate objective to those tests?
    My usual boring signature: Nothing

  5. #5
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    Quote Originally Posted by GinGin View Post
    I'm afraid the StopWatch control simply isn't accurate enough for whatever it is you're trying to achieve. If you simply want to see when a certain amount of time has passed, you could do it using a thread.

    vb Code:
    1. Dim i As UInt32 = 0
    2.         While (i < 5)
    3.             Threading.Thread.Sleep(1)
    4.         End While
    5.         '5 ms passed

    Or alternatively replacing
    vb Code:
    1. If Watch.Elapsed.Milliseconds = 5
    in your code with
    vb Code:
    1. If Watch.Elapsed.Milliseconds >= 5
    in which case it would fire if the elapsed milliseconds are either 5, or bigger than 5.
    This

    Code:
                Dim i As UInt32 = 0
                While (i < 5)
                    Threading.Thread.Sleep(1)
                End While
                '5 ms passed
    assumes, incorrectly, that the line after Threading.Thread.Sleep(1) will execute exactly 1 ms. later, and that the code takes 0 time to execute.

    I agree with Shaggy, what is the OP trying to accomplish?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  6. #6
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Too fast for VB to detect? Stopwatch.

    Quote Originally Posted by GinGin View Post
    I'm afraid the StopWatch control simply isn't accurate enough for whatever it is you're trying to achieve. If you simply want to see when a certain amount of time has passed, you could do it using a thread.
    Your information about StopWatches is out of date. Any PC which passes the "Vista Ready" test (i.e. practically every PC made in the last 8 years) has a high resolution stopwatch which counts Ticks of about 250 nanoseconds. You use it by checking the stopwatch's ElapsedTicks reading and dividing by StopWatch.Frequency (shared) to get the number of seconds. But starting and reading the StopWatch has an overhead of 2-3 microseconds, which effectively limits the accuracy to that level. But it's fine for measuring fractions of milliseconds. Using threads won't work with any accuracy because they communicate through event queues. BB

  7. #7
    New Member GinGin's Avatar
    Join Date
    Oct 2010
    Posts
    13

    Re: Too fast for VB to detect? Stopwatch.

    Quote Originally Posted by boops boops View Post
    Your information about StopWatches is out of date. Any PC which passes the "Vista Ready" test (i.e. practically every PC made in the last 8 years) has a high resolution stopwatch which counts Ticks of about 250 nanoseconds. You use it by checking the stopwatch's ElapsedTicks reading and dividing by StopWatch.Frequency (shared) to get the number of seconds. But starting and reading the StopWatch has an overhead of 2-3 microseconds, which effectively limits the accuracy to that level. But it's fine for measuring fractions of milliseconds. Using threads won't work with any accuracy because they communicate through event queues. BB
    By inaccurate I didn't mean the StopWatch wouldn't hit a point where it's ElapsedMilliseconds property is 5, but the lousy odds of managing to test a condition at that exact time.

  8. #8
    PowerPoster kaliman79912's Avatar
    Join Date
    Jan 2009
    Location
    Ciudad Juarez, Chihuahua. Mexico
    Posts
    2,593

    Re: Too fast for VB to detect? Stopwatch.

    To test this theory I wrote this code:

    Code:
       Dim stwTimer As Stopwatch = Stopwatch.StartNew()
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            stwTimer.Start()
            While stwTimer.ElapsedMilliseconds < 2000
                TextBox1.AppendText(stwTimer.ElapsedMilliseconds.ToString & vbCrLf)
            End While
            stwTimer.Stop()
        End Sub
    What it does it starts the stopwatch and appends the elapsedmilliseconds to a multiline textbox until 2 seconds have passed. Even though it is a really small loop I noticed 2 very important things. The first data written is 1913, which means the 2 seconds are almost up before the "while" completes the first loop! the second thing is that some numbers repeat, sometimes more than twice (like the 1914) but then some are skipped (1927) which tell me that performance of the code decreases while the textbox is being filled and in that case is not reliable to try to catch a specific milisecond.

    Here's a partial output of the code:

    1913
    1914
    1914
    1914
    1915
    1915
    1916
    1916
    1917
    1917
    1918
    1919
    1920
    1921
    1922
    1923
    1924
    1925
    1926
    1928
    1929
    1930
    Last edited by kaliman79912; Oct 17th, 2010 at 12:29 PM.

  9. #9
    New Member GinGin's Avatar
    Join Date
    Oct 2010
    Posts
    13

    Re: Too fast for VB to detect? Stopwatch.

    I tried that earlier today with a console app and only 50 numbers, some of which were still repeated and some skipped.

  10. #10
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Too fast for VB to detect? Stopwatch.

    I would expect that the textbox would slow over time, since that append text is going to throw out the existing string, create a new string with both the old information and the new information, then paint the whole thing into the textbox. That last step seems like it will get slower over time, as will the earlier steps, though probably those earlier ones won't change enough for anybody to really notice.
    My usual boring signature: Nothing

  11. #11
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Too fast for VB to detect? Stopwatch.

    The individual times recorded can't mean much. Besides the Append and the ToString methods, they could be affected by things going on in the framework (garbage collecting) and in the system (other processes). To measure how long it takes to append stuff to a textbox (assuming that's what you want to do) I would take an average like this:

    Code:
    Dim sw as StopWatch = StopWatch.Startnew
    For i as integer = 0 to 1000
        TextBox1.AppendText("SomeText" & vbCrLf)
    Next
    Console.WriteLine((sw.ElapsedMilliseconds / 1000).ToString("0.00"))
    BB

  12. #12
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    Try it this way to get a better idea of the speed and accuracy:

    Code:
        Dim stwTimer As New Stopwatch
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            RichTextBox1.Clear()
            stwTimer.Reset()
            stwTimer.Start()
            Dim sb As New System.Text.StringBuilder
            While stwTimer.ElapsedMilliseconds < 5 'limit the damage
                sb.AppendLine(stwTimer.ElapsedTicks.ToString) 'note ticks
            End While
            stwTimer.Stop()
            RichTextBox1.AppendText(sb.ToString)
        End Sub
    I am not sure what we are discussing anymore.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  13. #13
    PowerPoster kaliman79912's Avatar
    Join Date
    Jan 2009
    Location
    Ciudad Juarez, Chihuahua. Mexico
    Posts
    2,593

    Re: Too fast for VB to detect? Stopwatch.

    The point is, to answer the original question posted by Silhorn, the code is not reliable enaugh to catch a specific number in the ElapsedMiliseconds method in any case. You should do a range check or a grater than or some other variable to stop your code because most times you won't catch the 5.

  14. #14
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    Really?

    Code:
        Dim stwTimer As New Stopwatch
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            stwTimer.Reset()
            stwTimer.Start()
            Do While stwTimer.ElapsedMilliseconds < 5 'limit the damage
    
            Loop
            If stwTimer.ElapsedMilliseconds = 5 Then Stop
            stwTimer.Stop()
        End Sub
    Not that I am recommending this. As has been mentioned, the OP needs to provide a larger context.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  15. #15

    Thread Starter
    Junior Member
    Join Date
    Oct 2009
    Posts
    27

    Re: Too fast for VB to detect? Stopwatch.

    Thanks for your replies

    But seems like I have to provide more information.

    I am trying to design something that gives my program a heads up when every 10 milliseconds have passed. So maybe something like a Switch variable that changes to one when that 10th millisecond has been reached and back to 0 when it's over and then back to 1 when the next 10 milliseconds...
    This is so that i can get my program to execute something every 10 milliseconds.

    I knew this was going to be a little problem when i found out the system.timer and form timers could not output as low as 1 millisecond intervals.

    I did some searching and found out there was 2 ways that might work. QueryPerformanceCounter was said to have a resolution of less than 1millisecond. Then i found somewhere that someone said StopWatch was a command that was the same functionality as QueryPerformanceCounter.

    I did just found out though, and as stated here that the reason why it didn't pick up my 5ms was because the all the other coding I have in my program also takes time to run so that's probably why it may have missed the 5ms or any millisecond i put in. I confirmed this by making a new program with nothing but the code I used for the timing and it seemed to catch the 5ms pretty much most of the time.

    Is there a way I can make this workout without making it complicated?

    It's not very important but If i can get it to work it would be nice.

  16. #16

    Thread Starter
    Junior Member
    Join Date
    Oct 2009
    Posts
    27

    Re: Too fast for VB to detect? Stopwatch.

    I think i've found a solution.

    Discovered that threads are things which you can run 2 sections of code at the same time, I have done some basic testing so far and it looks like it works.

    I will report back if it is all good.

  17. #17
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Too fast for VB to detect? Stopwatch.

    You may want to try using the System.Timers.Timer instead of the normal Forms timer. The advantage is that it automatically uses a separate thread so it isn't held up by whatever else is going on in your program. By default it's a one-shot timer, but if you set its AutoReset property to true it fires at regular intervals. The event is called Elapsed instead of Tick but you program it in much the same way as a normal Timer.Tick.

    There are a few restrictions, though, because it uses a separate thread. For example, you can't update the UI by using Refresh or Update because that would cause a cross-threading error. But Invalidate works, because that goes via a queue.

    Like any events, a Forms.Timer.Tick or System.Timers.Timer.Elapsed event is only approximate. It's possible to measure time accurately down to zillionths of a second using a StopWatch or DateTime, but to trigger anything with that information in code requires raising an event and that doesn't happen in real time. This applies to VB.Net, CSharp and all the other managed languages. Normal Timer events can only be relied on to be accurate at an interval about 55 milliseconds (according to MSDN). An interval of 10 milliseconds is still useful for various things, but it's likely to be off by a few milliseconds now and then.

    There is also a timer called a Multimedia Timer which is used in WPF. It's a bit more accurate, I believe something like 30 milliseconds guaranteed. I've seen an article about using it in Windows Forms somewhere on the Code Project, but I haven't tried it.

    BB

  18. #18
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    What does, "I am trying to design something that gives my program a heads up when every 10 milliseconds have passed." In particular, "heads up."

    Code:
    Public Class Form1
    
        Private Sub Form1_FormClosing(ByVal sender As Object, _
                                      ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If Threading.Interlocked.Read(isRun) = 1L Then
                Button1.PerformClick()
                e.Cancel = True
                Exit Sub
            End If
        End Sub
    
        Private Sub Form1_Shown(ByVal sender As Object, _
                                ByVal e As System.EventArgs) Handles Me.Shown
            myDelegate = New CaptureIntrvl(AddressOf foobar)
            Dim l As Long = Threading.Interlocked.Exchange(isRun, 1L)
            Dim t As New Threading.Thread(AddressOf foo)
            t.Start()
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) Handles Button1.Click
            Dim l As Long = Threading.Interlocked.Exchange(isRun, 0L)
        End Sub
    
        Public Sub foobar(ByVal d As DateTime)
            TextBox1.Text = d.ToString("HH:mm:ss.ffffff")
        End Sub
    
        Dim isRun As Long = 0L
    
        Delegate Sub CaptureIntrvl(ByVal d As DateTime)
        Public myDelegate As CaptureIntrvl
    
        Public Sub foo()
            Dim notify As New TimeSpan(0, 0, 0, 0, 10)
            Dim d As DateTime = DateTime.Now
            Do
                If (DateTime.Now - d).TotalMilliseconds >= notify.TotalMilliseconds Then
                    d = DateTime.Now
                    Invoke(myDelegate, New Object() {d})
                End If
                Threading.Thread.Sleep(0)
            Loop While Threading.Interlocked.Read(isRun) = 1L
        End Sub
    End Class
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  19. #19
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Too fast for VB to detect? Stopwatch.

    There is a difference, also, between 'after 10ms' and 'every 10ms'. In addition, with such a tiny span, it's unlikely you will get a reliable operation on a non-deterministic operating system. Further, what you do when the event is raised can (and most likely will) have a significant impact on your timing.

    I believe the stopwatch object uses the performance timer objects 'under the hood', but I'd have to re-check that.

    All these timers mentioned have essentially perfect resolution - that is, they can measure down to the tick level. However, the accuracy is highly dependent on the OS, the surrounding code and the hardware.

    There will be a non-deterministic overhead that becomes much more significant as the interval you need to measure becomes smaller and smaller. While todays hardware and OS are of a much greater performance than [yesterday], measuring and doing something on a 10ms interval implies that it must be reliable and consistent - something you aren't going to get on a PC with a non-RTOS without specialized hardware.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  20. #20
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    Quote Originally Posted by SJWhiteley View Post
    There is a difference, also, between 'after 10ms' and 'every 10ms'. In addition, with such a tiny span, it's unlikely you will get a reliable operation on a non-deterministic operating system. Further, what you do when the event is raised can (and most likely will) have a significant impact on your timing.

    I believe the stopwatch object uses the performance timer objects 'under the hood', but I'd have to re-check that.

    All these timers mentioned have essentially perfect resolution - that is, they can measure down to the tick level. However, the accuracy is highly dependent on the OS, the surrounding code and the hardware.

    There will be a non-deterministic overhead that becomes much more significant as the interval you need to measure becomes smaller and smaller. While todays hardware and OS are of a much greater performance than [yesterday], measuring and doing something on a 10ms interval implies that it must be reliable and consistent - something you aren't going to get on a PC with a non-RTOS without specialized hardware.
    I agree with you Stephen.

    On my dual core system, just running this sample application, it appears to work. However I wouldn't bet my life on it always working for the reasons given by Stephen.

    Code:
    Public Class Form1
    
        Private Sub Form1_FormClosing(ByVal sender As Object, _
                                      ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If Threading.Interlocked.Read(isRun) = 1L Then
                Button1.PerformClick()
                e.Cancel = True
                Exit Sub
            End If
        End Sub
    
        Private Sub Form1_Shown(ByVal sender As Object, _
                                ByVal e As System.EventArgs) Handles Me.Shown
            myDelegate = New CaptureIntrvl(AddressOf foobar)
            Dim l As Long = Threading.Interlocked.Exchange(isRun, 1L)
            Dim t As New Threading.Thread(AddressOf foo)
            t.Start()
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) Handles Button1.Click
            Dim l As Long = Threading.Interlocked.Exchange(isRun, 0L)
        End Sub
    
        Public Sub foobar(ByVal ts As TimeSpan)
            TextBox1.Text = ts.TotalMilliseconds.ToString("N0")
        End Sub
    
        Dim isRun As Long = 0L
    
        Delegate Sub CaptureIntrvl(ByVal ts As TimeSpan)
        Public myDelegate As CaptureIntrvl
    
        Public Sub foo()
            Dim notify As New TimeSpan(0, 0, 0, 0, 10)
            Dim d As DateTime = DateTime.Now
            Do
                Dim ts As TimeSpan = DateTime.Now - d
                If ts.TotalMilliseconds >= notify.TotalMilliseconds Then
                    d = DateTime.Now
                    Invoke(myDelegate, New Object() {ts})
                End If
                Threading.Thread.Sleep(0)
            Loop While Threading.Interlocked.Read(isRun) = 1L
        End Sub
    End Class
    Last edited by dbasnett; Oct 18th, 2010 at 07:22 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  21. #21
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: Too fast for VB to detect? Stopwatch.

    For this to work with any kind of reliability you would want multiple cores and not a battery. After all, you are effectively busy waiting on one core, which is going to suck the power out of a battery pretty fast.
    My usual boring signature: Nothing

  22. #22
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,897

    Re: Too fast for VB to detect? Stopwatch.

    Quote Originally Posted by Shaggy Hiker View Post
    For this to work with any kind of reliability you would want multiple cores and not a battery. After all, you are effectively busy waiting on one core, which is going to suck the power out of a battery pretty fast.
    Agreed. I did mention the code environment, and you point about the battery is excellent.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width