שתף באמצעות


High Precision timer

Question

Friday, December 27, 2019 8:15 PM

I need to create multiple timers in my application, with intervals of 10 msecs.

The Windows timer allows down to one msec. interval but does not  look like it triggers the tick even to low values.

Can anybody provide a sample for this in VB.net?

Thanks

Ros

All replies (18)

Wednesday, January 1, 2020 8:53 AM ✅Answered

Hi ,

I think this snippet is useful to you , Give it a try

 Function Pwait(ByVal Myseconds As Double)

        Dim endTime As Date = Date.Now.AddSeconds(Myseconds)
        Do : Loop Until Date.Now > endTime

        Return 0

    End Function

Think it well you can add some modifications to (AddMinutes or AddHours) instead of (AddSeconds) 

It may help , Hope so

Regards From Egypt


Friday, December 27, 2019 8:19 PM

Hi

Why do you say that? Have you tried using a 10ms interval - if so, what working code did you try to execute in the 10ms time gap?

Regards Les, Livingston, Scotland


Friday, December 27, 2019 11:12 PM | 1 vote

This Code:

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Ticks = 0
        SW.Reset()
        SW.Start()
        Timer1.Start()

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Ticks += 1
        If Ticks >= 100 Then
            SW.Stop()
            Timer1.Stop()
            TextBox1.AppendText(SW.Elapsed.ToString & vbNewLine)
        End If
    End Sub

Produces this:

00:00:01.5490560
00:00:01.5584723
00:00:01.5537806
00:00:01.5514059
00:00:01.5486879
00:00:01.5595995
00:00:01.5539031
00:00:01.5537765
00:00:01.5535929
00:00:01.5483009
00:00:01.5609107

So it seems that the timer is pretty consistent, but not especially accurate at that low of an interval. Here is a comment I found:

"The various timer classes use a larger granularity. Both Threading.Timer and Timers.Timer use 1/64 second, which is 15.625 milliseconds."

I cannot post the link - I get this message:
Body text cannot contain images or links until we are able to verify your account.

I have been posting here for 8 years. . . . .


Saturday, December 28, 2019 12:09 AM

@Devon, all day there have been funky things going on and off. This happens now and then followed by things working again.

Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

NuGet BaseConnectionLibrary for database connections.

StackOverFlow


Saturday, December 28, 2019 12:25 AM | 1 vote

Hello,

There is a C# library that can be used with VB.NET found here.

Create a C# class project, dump the class MicroStopwatch in, compile. Next create a VB.NET console app, add a reference to the C# project and replace the default code in the console project with the following.

Module Module1

    Sub Main()
        MicroTimerTest()
        Console.ReadLine()
    End Sub
    Private Sub MicroTimerTest()
        ' Instantiate new MicroTimer and add event handler
        Dim microTimer As New MicroLibrary.MicroTimer()
        AddHandler microTimer.MicroTimerElapsed, AddressOf OnTimedEvent

        microTimer.Interval = 1000 ' Call micro timer every 1000µs (1ms)

        ' Can choose to ignore event if late by Xµs (by default will try to catch up)
        ' microTimer.IgnoreEventIfLateBy = 500; // 500µs (0.5ms)

        microTimer.Enabled = True ' Start timer

        ' Do something whilst events happening, for demo sleep 2000ms (2sec)
        Threading.Thread.Sleep(2000)

        microTimer.Enabled = False ' Stop timer (executes asynchronously)

        ' Alternatively can choose stop here until current timer event has finished
        ' microTimer.StopAndWait(); // Stop timer (waits for timer thread to terminate)


        Console.ReadLine()
    End Sub

    Private Sub OnTimedEvent(ByVal sender As Object, ByVal timerEventArgs As MicroLibrary.MicroTimerEventArgs)
        ' Do something small that takes significantly less time than Interval
        Console.WriteLine($"Count = {timerEventArgs.TimerCount:#,0}  Timer = {timerEventArgs.ElapsedMicroseconds:#,0} µs, " + $"LateBy = {timerEventArgs.TimerLateBy:#,0} µs, ExecutionTime = {timerEventArgs.CallbackFunctionExecutionTime:#,0} µs")
    End Sub
End Module

Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

NuGet BaseConnectionLibrary for database connections.

StackOverFlow


Saturday, December 28, 2019 11:01 AM | 1 vote

Impossible

VB works only on a multi programming (multi tasking) operating systems.

You need for that another program language on a OS like MS-Dos or Linux

Because that there can come every time an interval in Windows. A timer is never precise. 

https://en.wikipedia.org/wiki/Computer_multitasking

Success
Cor


Saturday, December 28, 2019 11:57 AM | 1 vote

You can use Multimedia Timers with P/Invoke : About Multimedia Timers

(I had posted a sample for a smooth scrolling with MM Timers)


Saturday, December 28, 2019 2:57 PM

Yes. Plus that shows how well we can count in windows. Not how accurate the actual time is. And if there is any other gui or system things then the timing can be affected slightly.

About the smoothest I have seen is the old fashioned thread timer (based on Armin Zingler example) as shown.

In the image the red line is the actual time interval plotted. The actual stopwatch ellapsed time values shown at the right ie 4.999 milliseconds.

So the example is running 5 millisecond intervals accurate to 0.001 milliseconds... correct ???

:)

The example makes the controls. Just cut and paste the code into an empty form. Change the form name as required.

 

 

Imports System.ComponentModel
Imports System.Threading

Public Class Form2
    Private WithEvents Button1 As New Button With {.Parent = Me,
        .Location = New Point(20, 20), .Text = "Start"}
    Private _Thread As Thread
    Private _Quit As Boolean
    Private Sw1, Sw2 As New Stopwatch
    Private gBuffer As BufferedGraphics
    Private Increment As Integer = 5  'time interval in milliseconds
    Private NextTime As Integer
    Private eTimes As New List(Of Single)

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
        Form2_Resize(0, Nothing)
        ThreadSet(False)
    End Sub

    Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
        ThreadSet(False)
        If gbuffer IsNot Nothing Then gbuffer.Dispose()
        gbuffer = BufferedGraphicsManager.Current.Allocate(Me.CreateGraphics, Me.ClientRectangle)
        ThreadSet(True)
    End Sub

    Private Sub Form2_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        If gbuffer IsNot Nothing Then gbuffer.Dispose()
        ThreadSet(False)
    End Sub

    Private Sub TMain()
        'timer thread
        Sw1.Restart()
        Sw2.Restart()
        NextTime = increment
        eTimes.Clear()

        Do
            If Sw1.ElapsedMilliseconds > NextTime Then
                NextTime += increment

                Sw2.Stop()

                'use ElapsedTicks as ElapsedMilliseconds rounds down so 29.99999 = 29 ms
                Dim dt As Single = CSng(1000 * Sw2.ElapsedTicks / CDbl(Sw2.Frequency))

                eTimes.Add(dt)

                Sw2.Restart()

                If eTimes.Count > 100 Then eTimes.RemoveAt(0)

                RenderScene(gbuffer.Graphics)
                gbuffer.Render()
            End If
        Loop Until _Quit

        _Thread = Nothing
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Button1.Text = "Stop" Then
            ThreadSet(False)
        Else
            ThreadSet(True)
        End If
    End Sub

    Private Sub ThreadSet(startmode As Boolean)
        If startmode Then
            Button1.Text = "Stop"
            _Quit = False
            _Thread = New Thread(AddressOf TMain)
            _Thread.Start()
        Else
            Button1.Text = "Start"
            Dim t As Thread = _Thread   'Copy reference to avoid race condition
            If t IsNot Nothing Then
                _Quit = True
                t.Join()
            End If
        End If
    End Sub

    Private Sub RenderScene(g As Graphics)

        With g
            .ResetTransform()
            .Clear(Color.White)
            .SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            'draw time interval graph
            Dim max As Integer = 30 'milliseconds max height of graph units on form

            g.ScaleTransform(CSng(ClientRectangle.Width / 110), CSng(ClientRectangle.Height / max))

            Using p As New Pen(Color.Red, CSng(2 * max / ClientRectangle.Height)),
                    pGrid As New Pen(Color.SkyBlue, CSng(max / ClientRectangle.Height)),
                    f As New Font("arial", CSng(max / 15))

                For x As Integer = 0 To 100 Step 20
                    g.DrawLine(pGrid, x, max - 0, x, max - CSng(0.8 * max))
                    g.DrawString(x.ToString, f, Brushes.Black, x, max - f.Height)
                Next

                For y As Integer = 0 To CInt(0.8 * max) Step 10
                    g.DrawLine(pGrid, 0, max - y, 100, max - y)
                    g.DrawString(y.ToString & " ms", f, Brushes.Black, 0, max - y)
                Next

                g.DrawString("Ellapsed (ms)", f, Brushes.DarkRed, 80, 0)

                For i As Integer = 1 To eTimes.Count - 1
                    g.DrawLine(p, i - 1, max - eTimes(i - 1), i, max - eTimes(i))
                    g.DrawString(eTimes(i).ToString, f, Brushes.DarkRed, 80, i * f.Height)
                Next

            End Using
        End With
    End Sub
End Class

Saturday, December 28, 2019 4:59 PM

Which timer? .Net has multiple timers, as in Timers.

Do you know what the minimum resolution is for your system? It varies based on hardware. See Timer.Interval Property. That page says:

If your app requires greater resolution than that offered by the Timer class or the system clock, use the high-resolution multimedia timers; see How to: Use the High-Resolution Timer.

That page also has sample code to determine the resolution of the system clock on the current system.

Sam Hobbs
SimpleSamples.Info


Monday, December 30, 2019 7:14 AM | 1 vote

Hi,

Maybe you can try to use timeGetTime function,which retrieves the system time, in milliseconds. The system time is the time elapsed since Windows was started. In addition, The timeBeginPeriod function  and timeEndPeriod function would also help.

    <DllImport("winmm")>
    Private Function TimeGetTime() As UInteger

    End Function
    <DllImport("winmm")>
    Private Sub TimeBeginPeriod(ByVal t As Integer)

    End Sub
    <DllImport("winmm")>
    Private Function TimeEndPeriod(ByVal t As Integer) As UInteger

    End Function

    Private Sub Timer()
        Dim timerstart As UInteger = TimeGetTime()

        While True
            Dim i As UInteger = 0

            While i < 10 'the time interval (ms)
                i = TimeGetTime() - timerstart
            End While

            timerstart = TimeGetTime()
            '......
            'Call Functions that need to run in a loop        
        End While
    End Sub

    Sub Main()
        Dim timerthread As Thread = New Thread(AddressOf Timer)
        TimeBeginPeriod(1)
        timerthread.Start()
    End Sub

Hope it be helpful.

Best Regards,

Julie

MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


Monday, December 30, 2019 12:52 PM

You can use Multimedia Timers with P/Invoke : About Multimedia Timers

(I had posted a sample for a smooth scrolling with MM Timers)

PS If one does not show a working example to prove the concept then one has not really answered the question iMHO ???

Anyone can say use the multimedia timer. But I dont see anyone making it work? And I dont see any examples working better than useing the stop watch as I have shown.

(although I am sure Castor can make it work, and I would like to see that, there is another api I cant think of getXXXellapsed or something?).

Just sayin... prove it...

:)

PS just showing code ix not proving it one must show the results too. Don't always expect us to run your code and make it prove your point.

:)

PS I am picking on everyone not just Castor.


Monday, December 30, 2019 6:10 PM

PS If one does not show a working example to prove the concept then one has not really answered the question iMHO ???

Anyone can say use the multimedia timer. But I dont see anyone making it work?

In other words you want us to read the documentation and write the code for you. If you mean you want someone to write code that does everything for your specific application then that is not reasonable. Your question in fact is not real clear about the exact requirements. If you want a sample showing the best that Windows is capable of then you just need to read my previous reply.

The precise timing you require might require a device driver. I do not know, that is my speculation. The timing requirements probably do require a real-time operating system as in:

Something I do not see said in those articles is that there have been versions of Windows, such as Windows CE, that were considered real-time. I think. But the important question is if Windows 10 is. See windows 10 real-time operating system - Google Search for more on that.

Sam Hobbs
SimpleSamples.Info


Tuesday, December 31, 2019 4:00 PM

PS If one does not show a working example to prove the concept then one has not really answered the question iMHO ???

Anyone can say use the multimedia timer. But I dont see anyone making it work?

In other words you want us to read the documentation and write the code for you. If you mean you want someone to write code that does everything for your specific application then that is not reasonable.

Sam Hobbs
SimpleSamples.Info

Hi Sam,

What I mean is why should anyone waste time researching your suggestion?

Based on all you have shown you may not even know what you are talking about?

Pehaps your solution is a waste of time while there are several solutions shown already with working code and proven reproducable results.

We should all try to make our answers complete enough and show something worth while to entice the forum members to bother looking at what we write.

Tom


Tuesday, December 31, 2019 7:29 PM

Anyone can say use the multimedia timer. But I dont see anyone making it work?

As I said, it depends on what you mean by making it work. The documentation I referenced has working examples.

What I mean is why should anyone waste time researching your suggestion?

Assuming it is a waste of time is a critical mistake if it is not a waste of time.

Based on all you have shown you may not even know what you are talking about?

Just look at the documentation.

This is obviously going nowhere. Reply with whatever you want to say, I am unsubscribing from this and I won't see anymore about this.

Sam Hobbs
SimpleSamples.Info


Tuesday, December 31, 2019 7:58 PM

Hi Sam en Tommy. 

This is in the documentation which is provided in this thread by Castorix. 

Windows multimedia is designed for use by C/C++ programmers. Familiarity with the Windows graphical user interface and message-driven architecture is required.

Fine trying to do that with VB for .Net.  

Therefore what are you discussing: "Is it theoretical possible". Most probably. With a program languages on a higher abstraction level than C/C++. Most probably not. Be aware it is not the .Net media (wpf) namespace. 

Cor

Success
Cor


Wednesday, January 1, 2020 3:18 PM

Anyone can say use the multimedia timer. But I dont see anyone making it work?

As I said, it depends on what you mean by making it work. The documentation I referenced has working examples.

What I mean is why should anyone waste time researching your suggestion?

Assuming it is a waste of time is a critical mistake if it is not a waste of time.

Based on all you have shown you may not even know what you are talking about?

Just look at the documentation.

This is obviously going nowhere. Reply with whatever you want to say, I am unsubscribing from this and I won't see anymore about this.

Sam Hobbs
SimpleSamples.Info

Sam,

I just mean in general, nothing personal.

In the past I researched the "multi media" timers based on other discussions and never really found anything usable by me. However, that does not mean there is none what do I know other than what I have shown.

So my earlier post to castor I actually mean lets see an example. I thought if anyone could do it it would be castor.

We get a group result with working examples that somehow compares to each posted result.

Then we can reach a useful conclusion and say this is good for that...

:)


Wednesday, January 1, 2020 3:47 PM

In the past I researched the "multi media" timers based on other discussions and never really found anything usable by me. However, that does not mean there is none what do I know other than what I have shown.

I used MM Timers for animations, like scrolling text, in C++ then in .NET

But now I use Direct2D for animations, a lot more powerful... (as fast in VB.NET as in C++)


Wednesday, January 1, 2020 6:12 PM

Hi Castor,

Charlie Chaplin knew already that for animations 1sec/25 is enough, currently there is often something as 1/30 used but that is still about 30 milliseconds. ( I know I'm on slippery ground with Tommy on board :-) )

The normal user recognisance of changes on a screen is even about 3 seconds (taken as general standard).

That can even be done with a normal windows form timer.

Probably the biggest problem from the OP is that he was talking about more events simultaneously (multiple timers), what makes it real difficult in my idea. You have ignored that all.   

Success
Cor