Results 1 to 23 of 23

Thread: [RESOLVED] High accuracy timer / delay

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Resolved [RESOLVED] High accuracy timer / delay

    Hey I'm quite the beginner in VB.NET so I don't know all the possibilities with the problem I'm having.
    I'm currently using the default VB.NET timer control, however after a few weeks of testing quite thoroughly I discovered that my delay was longer than it was supposed to be.

    Let me explain my situation:
    I am receiving values over my serial port which I then write to a chart so that I get a line curve (Spline). I add the chart points with my timer. Every 50 milliseconds I add a new values received by my serial port. This value is also added to my datagridview. so I can build up a nice grid overview including my system time (the time given by my computer itself).

    After a while using my program I discovered that the time is quite off. I used a stopwatch to time my actions and after 10 seconds I noticed that it were actually ~13 seconds in reality. I somewhere read that the VB.NET timers are not actually that precise even if you can input intervals of 1 ms. Apparently I need a high resolution timer to solve my problem, so here I am wondering what path to follow.
    I've read about a function called stopwatch, however I do not need a time between start and end, I need an accurate delay / timer.

    Any suggestions / idea's how I could solve my problem? Also if anything is unclear I happily will try to clear it up. Help would be VERY much appreciated!

  2. #2
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    Hello,

    Maybe something like this could help you out;

    Code:
    Imports System.ComponentModel
    
    Public Class Form1
    
        Private WithEvents Bgw As New ComponentModel.BackgroundWorker
        Private WithEvents St As New Diagnostics.Stopwatch
    
        Private Event Tick(Ms As Integer)
        Private CancelBgw As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            With Bgw
                .WorkerSupportsCancellation = True
                If Not .IsBusy Then
                    CancelBgw = False
                    .RunWorkerAsync()
                End If
            End With
        End Sub
    
        Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    
            Me.CancelBgw = True
    
        End Sub
    
        Private Sub Bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles Bgw.DoWork
    
            St.Start()
    
            While Not Me.CancelBgw
                If St.ElapsedMilliseconds >= 50 Then
                    RaiseEvent Tick(St.ElapsedMilliseconds)
                    St.Reset()
                    St.Start()
                End If
            End While
        End Sub
    
        Private Sub Form1_Tick(Ms As Integer) Handles Me.Tick
            Debug.Print(Ms.ToString)
        End Sub
    End Class
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  3. #3
    PowerPoster Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Bottesford, North Lincolnshire, England.
    Posts
    2,423

    Re: High accuracy timer / delay

    This is a well presented question, however we need details of how you're using the timer (timers).
    There are guys in this forum that will sort out your problem, but they're all going to need to see the relevant coding.


    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Quote Originally Posted by Goggy View Post
    Hello,

    Maybe something like this could help you out;

    Code:
    Imports System.ComponentModel
    
    Public Class Form1
    
        Private WithEvents Bgw As New ComponentModel.BackgroundWorker
        Private WithEvents St As New Diagnostics.Stopwatch
    
        Private Event Tick(Ms As Integer)
        Private CancelBgw As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            With Bgw
                .WorkerSupportsCancellation = True
                If Not .IsBusy Then
                    CancelBgw = False
                    .RunWorkerAsync()
                End If
            End With
        End Sub
    
        Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    
            Me.CancelBgw = True
    
        End Sub
    
        Private Sub Bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles Bgw.DoWork
    
            St.Start()
    
            While Not Me.CancelBgw
                If St.ElapsedMilliseconds >= 50 Then
                    RaiseEvent Tick(St.ElapsedMilliseconds)
                    St.Reset()
                    St.Start()
                End If
            End While
        End Sub
    
        Private Sub Form1_Tick(Ms As Integer) Handles Me.Tick
            Debug.Print(Ms.ToString)
        End Sub
    End Class
    I have tried to add this code, however it did not work out the way I hoped for. There is something blocking a second loop.

    Luckily you are dutch (I assume because of your signature :P) so maybe you will understand some of my coding.

    Code:
    Private Sub drawchart()
            receivedSerialData = ReceiveSerialData()
            Dim lines As String() = receivedSerialData.Split(vbLf)
    
            If lines(0).Length > 3 Then
                Double.TryParse(lines(0), analoge)
            End If
    
            Dim eindwaarde = (analoge / 5) - offset
    
            If SerialPort1.IsOpen = True Then
                If Chart1.Series(0).Points.Count > Val(maxval) Then
                    Chart1.Series(0).Points.RemoveAt(0)
                End If
    
                DataGridView1.Rows.Insert(0, DateTime.Now.ToString("dd/MM/yyyy--HH:mm:ss"), eindwaarde, gridid)
                Chart1.Series(0).Points.AddY(eindwaarde)
                gridid = Val(gridid) + 1
            Else
                SerialPort1.Open()
            End If
        End Sub
    I added this at the me.tick event.

    Thanks for your example though I will try and figure out more about this method!

    Quote Originally Posted by Poppa Mintin View Post
    This is a well presented question, however we need details of how you're using the timer (timers).
    There are guys in this forum that will sort out your problem, but they're all going to need to see the relevant coding.


    Poppa.
    I wouldn't mind showing relevant code. Please tell me what I should add (other than the code I presented above).

  5. #5
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    what do you mean "There is something blocking a second loop." ?
    Does the tick event only happens once? or does the code get hang up in the tick event? Or is the code producing an error?
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  6. #6

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    In the debug I can only see one cycle of code. Lets say I see the 50 ms debug once and then it just stops. The program doesn't crash or show any error.

    Edit: sorry it shows: Exception thrown: 'System.InvalidOperationException' in System.Windows.Forms.dll

  7. #7
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    would you be so kind as to put a try catch statement accross the tick event? and then see if it still doenst produce an error
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Quote Originally Posted by Goggy View Post
    would you be so kind as to put a try catch statement accross the tick event? and then see if it still doenst produce an error
    Sure thing, the result: it does keep up the loop now + "Exception thrown: 'System.InvalidOperationException' in System.dll".

    So right now I have:
    Code:
       Private Sub Form1_Tick(Ms As Integer) Handles Me.Tick
            Try
                Debug.Print(Ms.ToString)
                drawchart()
    
            Catch
            End Try
        End Sub
    Code:
        Private Sub drawchart()
            receivedSerialData = ReceiveSerialData()
            Dim lines As String() = receivedSerialData.Split(vbLf)
    
            If lines(0).Length > 3 Then
                Double.TryParse(lines(0), analoge)
            End If
    
            Dim eindwaarde = (analoge / 5) - offset
    
            If SerialPort1.IsOpen = True Then
                If Chart1.Series(0).Points.Count > Val(maxval) Then
                    Chart1.Series(0).Points.RemoveAt(0)
                End If
    
                DataGridView1.Rows.Insert(0, DateTime.Now.ToString("dd/MM/yyyy--HH:mm:ss"), eindwaarde, gridid)
                Chart1.Series(0).Points.AddY(eindwaarde)
                gridid = Val(gridid) + 1
            Else
                SerialPort1.Open()
            End If
        End Sub

  9. #9

  10. #10
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    Ok , i susspect it has to do with cross threading, trying to update the form thread from the background worker thread....
    mmmm...

    ok lets try it like so
    Code:
    Public Class Form1
    
        Private WithEvents Bgw As New ComponentModel.BackgroundWorker
        Private WithEvents St As New Diagnostics.Stopwatch
    
        Private Event Tick(Ms As Integer)
        Private CancelBgw As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            With Bgw
                .WorkerReportsProgress = True                '<----Added
                .WorkerSupportsCancellation = True
                If Not .IsBusy Then
                    CancelBgw = False
                    .RunWorkerAsync()
                End If
            End With
        End Sub
    
        Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    
            Me.CancelBgw = True
    
        End Sub
    
        Private Sub Bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles Bgw.DoWork
    
            St.Start()
    
            While Not Me.CancelBgw
                If St.ElapsedMilliseconds >= 50 Then
                    Bgw.ReportProgress(1)                       '<----Added       (Its a bit of an hack)
                    'RaiseEvent Tick(St.ElapsedMilliseconds)    '<----Removed
    
                    St.Reset()
                    St.Start()
                End If
            End While
        End Sub
    
        'Private Sub Form1_Tick(Ms As Integer) Handles Me.Tick
        '    Debug.Print(Ms.ToString)
        'End Sub
    
        Private Sub Bgw_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Bgw.ProgressChanged
            'Result beeing that the drawchart sub is called from the ui thread.
            drawchart
        End Sub
    End Class
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  11. #11

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Quote Originally Posted by Goggy View Post
    Ok , i susspect it has to do with cross threading, trying to update the form thread from the background worker thread....
    mmmm...

    ok lets try it like so
    Code:
    Public Class Form1
    
        Private WithEvents Bgw As New ComponentModel.BackgroundWorker
        Private WithEvents St As New Diagnostics.Stopwatch
    
        Private Event Tick(Ms As Integer)
        Private CancelBgw As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            With Bgw
                .WorkerReportsProgress = True                '<----Added
                .WorkerSupportsCancellation = True
                If Not .IsBusy Then
                    CancelBgw = False
                    .RunWorkerAsync()
                End If
            End With
        End Sub
    
        Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    
            Me.CancelBgw = True
    
        End Sub
    
        Private Sub Bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles Bgw.DoWork
    
            St.Start()
    
            While Not Me.CancelBgw
                If St.ElapsedMilliseconds >= 50 Then
                    Bgw.ReportProgress(1)                       '<----Added       (Its a bit of an hack)
                    'RaiseEvent Tick(St.ElapsedMilliseconds)    '<----Removed
    
                    St.Reset()
                    St.Start()
                End If
            End While
        End Sub
    
        'Private Sub Form1_Tick(Ms As Integer) Handles Me.Tick
        '    Debug.Print(Ms.ToString)
        'End Sub
    
        Private Sub Bgw_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Bgw.ProgressChanged
            'Result beeing that the drawchart sub is called from the ui thread.
            drawchart
        End Sub
    End Class
    With this code it does work, but I think due to it being on another thread It's now having problems updating the datagrid as well.
    Currently the chart is working very fluently when my datagrid is "hidden" (I have a button to expand my form and it will show the list of values in the datagrid). When I expand my form and open up my datagridview the chart is starting to lag very badly until I close the expanded part again.


    Code:
    Private Sub drawchart()
    ~~~~~~
    DataGridView1.Rows.Insert(0, DateTime.Now.ToString("dd/MM/yyyy--HH:mm:ss"), eindwaarde, gridid)
    ~~~~~~
    end sub

  12. #12
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    how many rows are there in the datagrid?
    I guess its taking up more then 50 ms to insert the row.
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  13. #13

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Well every 50 ms a new gets added. Sometimes there are over 50k rows. Would this be the bottleneck? Any advice on this?

  14. #14
    Addicted Member Goggy's Avatar
    Join Date
    Oct 2017
    Posts
    196

    Re: High accuracy timer / delay

    Maybe save the data to a database, and only show the last 100 rows or so?
    Utterly useless, but always willing to help

    As a finishing touch god created the dutch

  15. #15
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: High accuracy timer / delay

    Good hardware has a clock and clocks itself with a degree of accuracy you pay for. I worked at a test and measurement company for a long time, and generally the sample rate was just part of configuring communication with our devices. The really good ones could sample down to the nanosecond range. You can't make the WinForms timer do this. It's designed to be polite when the machine is under stress. That means you can never guarantee you get events at the interval you want. If the work you do takes longer than a timer interval, you miss intervals. You can't get around that.

    Part of acquiring data is presenting it, and even when the hardware supports clocking if the data arrives faster than you can display it, you lag. 50ms intervals are a little too fast, in my opinion, to expect real-time display, especially considering getting your data from "raw" to "DataGridView" probably involves several transformations, both explicit and implicit.

    When sample rate exceeds processing speed, you have to buffer. That's something good hardware does automatically as well, but often you can get cheaper versions of good hardware that don't buffer. All it really means is instead of this:
    Code:
    Every 50ms:
      * Get a sample.
      * Display a sample.
    You switch to something like this:
    Code:
    Every 50ms:
      * (Worker thread.) Get a sample and store it.
    
    Every 5s:
      * (UI thread.) Get all current samples and display them.
    This way, your UI logic doesn't interfere with your sampling logic, and if it takes slightly longer to process data than acquire it you can find a way to manage. This is how that nanosecond hardware I mentioned HAS to operate: few machines can process and display data in the GB range per second. So they sample for a second or two, dumping samples into a buffer, then they take their sweet time processing the data in the buffer and display it.

    So if hardware clocking/buffering isn't an option, you should make a thread to do your buffering. It should sample at 50ms using System.Threading.Timer, but you need to keep in mind that one doesn't guarantee 50ms either. So you should also timestamp your data so you understand the true sample delta. (This is another thing good hardware/drivers do for you.)

    The UI thread should periodically empty the buffer, process the data, and display it. This interval should be much slower, 1-2s seems reasonable.

    This falls apart if it takes you more than 50ms of processing per data point. If that is true, you need to either consider "sample for some time, then stop sampling and wait for processing to catch up" or "cut the sample rate to 100ms or higher until processing catches up", or "It's OK to drop some points if we're behind", etc. You'll run out of memory if you don't pick a "backpressure" strategy.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

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

    Re: High accuracy timer / delay

    What does method 'ReceiveSerialData' look like? If it contains a blocking serial port method then that will affect your timer.

    edit: See sitten made a suggestion at the same time, and I totally agree about the structure he is recommending.
    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

  17. #17

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Taken your two replies I could store my UI data from the datagrid into an array and display this one based on a different timer / thread. This way the chart is accurate which is the most important part, due to being the soul purpose of this application.

    Storing it in a database itself (I'm thinking about MySQL or something when I see the word database, correct me if I'm wrong), wouldn't be something I could do due to this program being on multiple machines in various locations without internet connection.

    Thanks for all the help you guys gave me. I will try and see how it goes when I separate the chart from the grid!

  18. #18
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: High accuracy timer / delay

    I was just revisiting this subject a week or so ago because of another thread.
    Depending on how much jitter is acceptable, the following is some test code that just uses the timer running as fast as it can (which won't take too much CPU), and using a stopwatch to monitor the passage of time. The code assumes the timer will be running at least 64 hz (15.625ms interval) so uses approximately half of that value (8 ms) as a threshold. If the timer tick is within +/- 8 ms of the desired trigger time you should execute your code and add the desired interval to your trigger time.
    Since the timer ticks occur on the GUI thread, you won't have cross threading issues to deal with.

    Here is a sample output of the example (you would remove all that debug stuff in your usage). In this case we wanted to execute every 50ms for a period of 3 seconds.
    The expected result would be 20 times per second for 3 seconds would be 60 executions over a period of 3000ms.
    The printout counts the runs, the time that it executed, the ideal desired time ("Trigger"), the delta between when when it ran vs the ideal time it should have run.
    It also shows ticks where the processing was skipped to achieve the desired rate.
    Code:
    Process 55 Ran at 2753ms elapsed time, Trigger 2750, delta 3
    Skipping this timer tick
    Skipping this timer tick
    Process 56 Ran at 2793ms elapsed time, Trigger 2800, delta -7
    Skipping this timer tick
    Skipping this timer tick
    Process 57 Ran at 2843ms elapsed time, Trigger 2850, delta -7
    Skipping this timer tick
    Skipping this timer tick
    Process 58 Ran at 2893ms elapsed time, Trigger 2900, delta -7
    Skipping this timer tick
    Skipping this timer tick
    Skipping this timer tick
    Process 59 Ran at 2953ms elapsed time, Trigger 2950, delta 3
    Skipping this timer tick
    Skipping this timer tick
    Process 60 Ran at 3003ms elapsed time, Trigger 3000, delta 3
    Process ran 60 times, taking 3003ms
    You see the process ran the desired 60 times over a period of 3003 ms, so only + 3 ms over ideal. That +3 ms over is not accumulative, so if you ran six seconds or sixty seconds, you would still be within a portion of a timer tick of the correct time, and have executed the number of times desired over that period.
    Code:
    Public Class Form1
      Private DesiredTickInterval As Integer 'interval in ms
      Private DesiredTime As Long 'How long we want to process in ms
      Private TriggerTime As Long 'Updated to define when we should process next
      Private sw As New Stopwatch
      Private ProcessRuns As Integer
    
      Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        sw.Reset()
        DesiredTickInterval = 50 '50ms means process 20 times per second
        TriggerTime = DesiredTickInterval 'intialize first trigger
        ProcessRuns = 0
        DesiredTime = 3000  'process for 3 second
        Timer1.Interval = 1 'let timer fire as quick as it can (probably 64 times per second)
        Timer1.Start()      'start the timer
        sw.Start()          'start our elapsed time stopwatch
      End Sub
    
      Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        Dim currentElapsedTime As Long = sw.ElapsedMilliseconds
    
        Dim deltaTime As Long = currentElapsedTime - TriggerTime
        If (currentElapsedTime >= TriggerTime) Or
          (Math.Abs(deltaTime) <= 8) Then  'allow to happen a little before or after the desired time, so a little steadier
          ProcessRuns += 1
          Debug.Print("Process {1} Ran at {0}ms elapsed time, Trigger {2}, delta {3}",
                      currentElapsedTime.ToString, ProcessRuns.ToString, TriggerTime.ToString, deltaTime.ToString)
          TriggerTime += DesiredTickInterval  'update our trigger for the next desired time
    
        Else
          Debug.Print("Skipping this timer tick")
        End If
        If currentElapsedTime >= DesiredTime Then
          sw.Reset()
          Timer1.Stop()
          Debug.Print("Process ran {0} times, taking {1}ms", ProcessRuns.ToString, currentElapsedTime.ToString)
        End If
    End Class
    p.s. Several posts while I was digging this up. I do agree with SittenSpynne and normally do separate the data processing from the GUI updates as well, but in other cases I do need a relatively stable trigger for updating Simulation models at a given number of times per second within acceptable jitter and use a method like the above to achieve that in simple scenarios. In more stringent requirements, then the trigger is tied to a real hardware backed solution as he mentioned, e.g. a hardware based realtime clock card or a video based start of frame message.
    Last edited by passel; Dec 18th, 2017 at 10:05 AM. Reason: Removed unused variable from Timer tick sub

  19. #19
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: High accuracy timer / delay

    If you have a timer set to fire every 10 seconds and then it performs a 1 second operation it will effectively delay the timer for a second ... so then when it comes to wait again you will be 1 second out ... then 2 etc.

    There are ways to do this with threads etc ... but just say you want to update something every 50ms and you have operations that fire off evey 50 ms on another thread ... but the operations on a slower computer take 1 second to run ... if you do this you can run into resource issues as more and more threads are created on the computer that can't keep up, each one potentially running slower than the last!

    Since this is an interface you may be tempted to run a thread timer and invoke the form ... this will be accurate but can also produce the issue of delay between tick and execution ... if the computer is too slow to execute the commands before the next interval... these are internally BeginInvoked ... so this will queue up and cause the same issue.

    I think that the best solution (with such a small delay updating an interface) would be to either store the data with a small interval on a thread timer (every 50ms) - but store the time with it as a safeguard .. so if somehow a few ms/s are missed as getting the data takes longer in one instance takes a little longer, it can be plotted a little bit "off its point"... Just storing the data would prob be fast ... I would then prob invoke an update to the graph that happens every so often ... lets say 250ms ... from the same thread timer.

    Structure for storing the queued points:
    VB.Net Code:
    1. Public Structure DataValues
    2.     Public ReadOnly Property Time As Date
    3.     Public ReadOnly Property Value As Integer
    4.     Public Sub New(Time As Date, Value As Integer)
    5.         Me.Time = Time : Me.Value = Value
    6.     End Sub
    7. End Structure

    Your thread timer event code could look like this:
    VB.Net Code:
    1. Static QueuedPoints As New List(Of DataValues)
    2. Static LastDrawnTime As Date
    3.  
    4. 'add to QueuedPoints here
    5. QueuedPoints.Add(New DataValues(Now, value))
    6.  
    7. 'update the graph if last drawn more than 250ms ago
    8. If Now.Subtract(LastDrawnTime).TotalMilliseconds >= 250 Then
    9.     LastDrawnTime = Now
    10.     'me is the form you want to invoke...
    11.     'we need to pass the queued points into it as an array so we can clear it on this thread while the graph is updating
    12.     Me.BeginInvoke(Sub(qp As DataValues())
    13.                        'update graph with queued points here
    14.  
    15.                    End Sub, QueuedPoints.ToArray)
    16.     QueuedPoints.Clear()
    17. End If
    ... Value above would be your new value for the graph

    Kris

  20. #20
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: High accuracy timer / delay

    Actually since this is presumably not time critical and just for updating the graph I would prob do it the way you are doing now ... and just store the last tick and the new tick in some way (either as a time / stopwatch etc) and use that to get the interval between the points ... rather than assuming that they will be 50ms

    Kris

  21. #21

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Currently I store the data for my grid in an array list. This way I do save the important information for my grid, but the actual control (datagridview) is updated when I stop the timer interval of 50 ms. This way I get both what I want with the precision that I want. Thank you all for your kind suggestions

  22. #22
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: High accuracy timer / delay

    You should consider using a specifically-typed List(Of T) instead of an ArrayList.

    ArrayList has been obsolete since .NET 2.0, which was VS 2005. Any book or tutorial that uses it is a good candidate for "out of date enough to be irrelevant". It stores items as the type "Object". That's not a "real" type for many things. If you're storing Doubles or Integers or other certain kinds of type, that means before you get to actually use them, a process called "unboxing" has to occur. Performance penalties incurred by boxing/unboxing used to be one of the biggest problems in .NET. It was the sole motivation for Generics. Then Microsoft got really excited about designing frameworks that ignore it so no one really thinks about it anymore.

    But if you're doing DAQ with lots of samples, you ought to get a nice performance boost out of using List(Of Double) instead of, say, an ArrayList with Doubles inside. Also: internally both ArrayList and List(Of T) resize themselves in powers of two. So it starts with a capacity of 16 by default, then resizes to 32 when you add the 17th item, resizes to 64 when you add the 33rd item, and so on. These resizes are very expensive, so you want to minimize them. If you expect 1000 samples, pre-set your capacity to 1024 or so for a margin. If you expect 10,000, go ahead and pre-set the capacity to 11,000 or so.

    Switching away from ArrayList and pre-setting the capacity ought to bring about more consistent performance.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  23. #23

    Thread Starter
    Junior Member
    Join Date
    Apr 2013
    Posts
    27

    Re: High accuracy timer / delay

    Quote Originally Posted by Sitten Spynne View Post
    You should consider using a specifically-typed List(Of T) instead of an ArrayList.

    ArrayList has been obsolete since .NET 2.0, which was VS 2005. Any book or tutorial that uses it is a good candidate for "out of date enough to be irrelevant". It stores items as the type "Object". That's not a "real" type for many things. If you're storing Doubles or Integers or other certain kinds of type, that means before you get to actually use them, a process called "unboxing" has to occur. Performance penalties incurred by boxing/unboxing used to be one of the biggest problems in .NET. It was the sole motivation for Generics. Then Microsoft got really excited about designing frameworks that ignore it so no one really thinks about it anymore.

    But if you're doing DAQ with lots of samples, you ought to get a nice performance boost out of using List(Of Double) instead of, say, an ArrayList with Doubles inside. Also: internally both ArrayList and List(Of T) resize themselves in powers of two. So it starts with a capacity of 16 by default, then resizes to 32 when you add the 17th item, resizes to 64 when you add the 33rd item, and so on. These resizes are very expensive, so you want to minimize them. If you expect 1000 samples, pre-set your capacity to 1024 or so for a margin. If you expect 10,000, go ahead and pre-set the capacity to 11,000 or so.

    Switching away from ArrayList and pre-setting the capacity ought to bring about more consistent performance.
    Thank you for the information. I now use a list of strings to collect all the data for my datagridview. Upon completion of the serialport data it will put all the datagrid data in the list. This method seems to working very quick and has good results so far.

    Thank you all for helping me out here!

Tags for this Thread

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