locked
Pausing for a specified millisecond, microsecond, or nanosecond duration RRS feed

  • General discussion

  • So I got an email earlier from someone asking about how to make a pause function, so I figured I would also share that here(even though most of you already probably know) So, there's not a whole lot to say, so here it is.

    Public Class Form1
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim Seconds As Integer = 1
            MsgBox(SpecialWait.waitMilli(1000))
            MsgBox(SpecialWait.waitMicro(1000000))
            MsgBox(SpecialWait.waitNano(1000000000))
        End Sub
    End Class
    Class SpecialWait
        'Set up Some Constants
        'Nano Second
        Public Const nSecond As Double = 0.000000001
        'Micro Second
        Public Const uSecond As Double = 0.000001
        'Millisecond
        Public Const mSecond As Double = 0.001
        'Calculate the quantity of ticks per nanosecond, microsecond, and millisecond
        Public Shared ReadOnly TicksPerNanoSecond As Double = Stopwatch.Frequency * nSecond
        Public Shared ReadOnly TicksPerMicroSecond As Double = Stopwatch.Frequency * uSecond
        Public Shared ReadOnly TicksPerMillaSecond As Double = Stopwatch.Frequency * mSecond
        'Create the stopwatch outside of the wait functions, that way they
        'don't spend time creating the stopwatch
        Private Shared Sw As New Stopwatch
        'Accurate within 1/2 of a millisecond
        Public Shared Function waitMilli(MilliSeconds As Long) As String
            'Re-start the stopwatch
            Sw.Restart()
            'perform the wait
            Do
                'Compare the elapsed ticks, to the amount of ticks in the
                'total amount of milliseconds you want to wait
            Loop Until (Sw.ElapsedTicks >= (TicksPerMillaSecond * MilliSeconds))
            Sw.Stop()
            'Normally this would be a sub and not a function that returned anything
            'This returns a string to show the aproximate 
            'duration of the wait
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds & " milli Seconds)"
        End Function
        'Accurate within 0-10 micro seconds
        Public Shared Function waitMicro(MicroSeconds As Long) As String
            Sw.Restart()
            Do
            Loop Until (Sw.ElapsedTicks >= (TicksPerMicroSecond * MicroSeconds))
            Sw.Stop()
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds * 1000 & " micro Seconds)"
        End Function
        'Accurate within 500-1000 nano seconds(no real difference in accuracy from micro)
        Public Shared Function waitNano(nanoSeconds As Long) As String
            Sw.Restart()
            Do
            Loop Until (Sw.ElapsedTicks >= (TicksPerNanoSecond * nanoSeconds))
            Sw.Stop()
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds * 1000000 & " nano Seconds)"
        End Function
    End Class


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Monday, May 21, 2012 8:19 AM
    Moderator

All replies

  • This is pretty common if you don't care about simply eating up the CPU cycles, but there's very rarely a need for a pause, anyway, especially one of such precision. It does demonstrate the power of the stopwatch - I believe it accesses to the Win32 API High performance timer under the hood, which was used for better timing in VB6.

    Basically, beware of the drawbacks of using this method.


    Stephen J Whiteley

    Monday, May 21, 2012 2:09 PM
  • Paul,

    This is quite precise inside the class, but it does not count the time it takes to do the call the the function and the time it takes for the function to return

    This code shows that calling a 1 Microsecond wait, does in fact create a 1500 microseconds wait time !!!

    Because it takes 1500 microsecond for the call and the return to the function to be done

    Public Class Form1
        Private sw1 As New Stopwatch
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            sw1.Start()
            SpecialWait.waitMicro(1)
            sw1.Stop()
            Dim Dif As Long = CLng((sw1.ElapsedTicks - SpecialWait.Sw.ElapsedTicks) / SpecialWait.TicksPerMicroSecond)
            Button1.Text = Dif.ToString
        End Sub
    End Class
    Class SpecialWait
        'Set up Some Constants
        'Nano Second
        Public Const nSecond As Double = 0.000000001
        'Micro Second
        Public Const uSecond As Double = 0.000001
        'Millisecond
        Public Const mSecond As Double = 0.001
        'Calculate the quantity of ticks per nanosecond, microsecond, and millisecond
        Public Shared ReadOnly TicksPerNanoSecond As Double = Stopwatch.Frequency * nSecond
        Public Shared ReadOnly TicksPerMicroSecond As Double = Stopwatch.Frequency * uSecond
        Public Shared ReadOnly TicksPerMillaSecond As Double = Stopwatch.Frequency * mSecond
        'Create the stopwatch outside of the wait functions, that way they
        'don't spend time creating the stopwatch
        Public Shared Sw As New Stopwatch
        'Accurate within 1/2 of a millisecond
        Public Shared Function waitMilli(ByVal MilliSeconds As Long) As String
            'Re-start the stopwatch
            Sw.Start()
            'perform the wait
            Do
                'Compare the elapsed ticks, to the amount of ticks in the
                'total amount of milliseconds you want to wait
            Loop Until (Sw.ElapsedTicks >= (TicksPerMillaSecond * MilliSeconds))
            Sw.Stop()
            'Normally this would be a sub and not a function that returned anything
            'This returns a string to show the aproximate 
            'duration of the wait
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds & " milli Seconds)"
        End Function
        'Accurate within 0-10 micro seconds
        Public Shared Function waitMicro(ByVal MicroSeconds As Long) As String
            Sw.Start()
            Do
            Loop Until (Sw.ElapsedTicks >= (TicksPerMicroSecond * MicroSeconds))
            Sw.Stop()
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds * 1000 & " micro Seconds)"
        End Function
        'Accurate within 500-1000 nano seconds(no real difference in accuracy from micro)
        Public Shared Function waitNano(ByVal nanoSeconds As Long) As String
            Sw.Start()
            Do
            Loop Until (Sw.ElapsedTicks >= (TicksPerNanoSecond * nanoSeconds))
            Sw.Stop()
            Return "(Elapsed:" & Sw.Elapsed.TotalMilliseconds * 1000000 & " nano Seconds)"
        End Function
    End Class

    Monday, May 21, 2012 4:28 PM
  • I definitely agree that using a Do-Loop while waiting for a stopwatch to tick a certain amount of times can take a pretty hefty toll on your CPU. I have never really noticed a huge problem when I use this for a few seconds or less. Although accurate, I certainly would not suggest using this for extended periods of time, such as minutes or even hours. If you need an event to happen every few minutes, thread.sleep would probably suffice. If you need an event to happen in the range of hours or days, I would suggest integrating task scheduler(or thread.sleep, depending on your needs).

    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Monday, May 21, 2012 4:35 PM
    Moderator
  • Penny -

    You can also try directly putting the wait loop where you need it, instead of using a class, this will yield the 0-10 microseconds precision(at least it does on my i5 CPU).

    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim Microseconds As Integer = 1
            Dim WaitTime As Double = SpecialWait.TicksPerMicroSecond * Microseconds
            SpecialWait.Sw = Stopwatch.StartNew
            Do
            Loop Until (SpecialWait.Sw.ElapsedTicks >= WaitTime)
            Dim Dif As Double = (SpecialWait.Sw.ElapsedTicks - SpecialWait.TicksPerMicroSecond) * Microseconds
            Button1.Text = Dif.ToString
        End Sub
    End Class
    Class SpecialWait
        Public Const nSecond As Double = 0.000000001
        Public Const uSecond As Double = 0.000001
        Public Const mSecond As Double = 0.001
        Public Shared ReadOnly TicksPerNanoSecond As Double = Stopwatch.Frequency * nSecond
        Public Shared ReadOnly TicksPerMicroSecond As Double = Stopwatch.Frequency * uSecond
        Public Shared ReadOnly TicksPerMillaSecond As Double = Stopwatch.Frequency * mSecond
        Public Shared Sw As New Stopwatch
    End Class


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.





    Monday, May 21, 2012 5:06 PM
    Moderator
  • Penny -

    You can also try directly putting the wait loop where you need it, instead of using a class, this will yield the 0-10 microseconds precision(at least it does on my i5 CPU).

    That is the way to go

    Monday, May 21, 2012 5:11 PM
  • Penny -

    You can also try directly putting the wait loop where you need it, instead of using a class, this will yield the 0-10 microseconds precision(at least it does on my i5 CPU).

    That is the way to go

    Penny-

    Thank you, a definite improvement!


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.


    Monday, May 21, 2012 5:14 PM
    Moderator