0

I have a sub that calculates arrays for graph, and another sub that plots graph. there are two threads one for calculation(getArrayForGraph()) and another for plotting graph.

now I want graph to plot along side array update function as array is very long(10 000 000) making whole process very very slow.

How I start updating graph as soon as points available for graph. or which is the best way to solve performance problem.

Sub getArrayForGraph()

    Dim time As Single = 0, finalTime As Single = 0

    Dim timeinterval As Decimal  'function calulates values in picoseconds
    Dim timeforGraph() As Long
    ReDim timeforGraph(TotalSample - 1)

    For index = 0 To TotalSample - 1
        If index = 0 Then
            finalTime = time
        Else
            finalTime += timeinterval
        End If
        timeforGraph(index) = Math.Round(finalTime, 3)
    Next
End Sub

Sub plotGraph()

    Chart1.Series("series1").Points.DataBindXY(timeforGraph, bufferDMv)
      'bufferAMV is array calculated from another for loop
end sub
3
  • How often is getArrayForGraph called? Commented Sep 6, 2017 at 15:07
  • when user click on update button it refresh graph for inputs given so I will say once Commented Sep 7, 2017 at 13:54
  • The main issue is that MSChart can't handle that many data points. Can you even plot it at all? You may need to aggregate the data by, say, millisecond, plotting the average data for each millisecond vs. the first/average/last time down to millisecond. Commented Sep 7, 2017 at 18:32

1 Answer 1

1

Here's a complete example. It uses a BackgroundWorker to perform the work, which signals to the UI to update. It also aggregates the data. I chose to display only 2000 points because 1. MSChart can't handle a lot of points, and 2. my display is only 1920 pixels wide, so there is no point to try to display more. This example will plot 1 point for every 5k (10M / 2k) points, which is x: the latest time, and y: the average value. You could also take the average time if you prefer but this plots neater.

It doesn't include your specific variables, because there was some missing information. But you should get the idea how it works and make it work in your environment

Public Class Form1

    Private worker As System.ComponentModel.BackgroundWorker

    Private chartX As New List(Of Long)()
    Private chartY As New List(Of Long)()

    ' settings for demo
    Private count As Long = 10000000
    Private numberOfGroups As Long = 2000
    Private groupSize As Long = count / numberOfGroups

    Private Sub doWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
        ' holds chunk of data to be grouped
        Dim temp As New List(Of Tuple(Of Long, Long))()
        For i As Long = 1 To count
            ' generate some scientific data!
            temp.Add(New Tuple(Of Long, Long)(i, Convert.ToInt64(i * Math.Sin(Math.PI * i / count) * Math.Sin(i))))
            ' make this happen 10 times
            If i Mod count / 10 = 0 Then
                ' group the time and data into same groupings
                Dim aggregate =
                    temp.
                    Select(Function(d, index) New Tuple(Of Integer, Tuple(Of Long, Long))(index, d)).
                    GroupBy(Function(d) Math.Floor(d.Item1 / groupSize))
                ' take the latest time
                Dim xAggregate =
                    aggregate.
                    Select(Function(a) a.Max(Function(b) b.Item2.Item1)).
                    ToArray()
                ' take the average data
                Dim yAggregate =
                    aggregate.
                    Select(Function(a) Convert.ToInt64(a.Average(Function(b) b.Item2.Item2))).
                    ToArray()
                ' clear temp data
                temp.Clear()
                ' -- calling resetChartData() here would make the chart display only the currently processed data
                ' -- might be useful if you were displaying data from an oscilloscope for instance
                ' resetChartData()
                ' add the aggregate data to the chart source data
                chartX.AddRange(xAggregate)
                chartY.AddRange(yAggregate)
                ' report progress (initiate charting)
                DirectCast(sender, System.ComponentModel.BackgroundWorker).ReportProgress(Convert.ToInt32(100 * i / count))
            End If
        Next
    End Sub

    Private Sub progressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs)
        ' ui thread runs here.
        ' perform minimal ui operations as not to slow down ui thread
        ' added a progress bar, nice to see
        ProgressBar1.Value = e.ProgressPercentage
        ' databind the data
        Chart1.Series("Series1").Points.DataBindXY(chartX, chartY)
    End Sub

    Private Sub resetChartData()
        chartX.Clear()
        chartY.Clear()
    End Sub

    Private Sub runWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs)
        Button1.Enabled = True
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' to prevent double clicks
        Button1.Enabled = False
        worker = New System.ComponentModel.BackgroundWorker()
        AddHandler worker.DoWork, AddressOf doWork
        AddHandler worker.ProgressChanged, AddressOf progressChanged
        AddHandler worker.RunWorkerCompleted, AddressOf runWorkerCompleted
        worker.WorkerReportsProgress = True
        ' do work on background thread
        worker.RunWorkerAsync()
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' set up chart
        Chart1.Series.Add("Series1")
        Chart1.Series.Single().MarkerStyle = DataVisualization.Charting.MarkerStyle.None
        Chart1.Series.Single().ChartType = DataVisualization.Charting.SeriesChartType.FastLine
        Chart1.Legends.Clear()
    End Sub

End Class
Sign up to request clarification or add additional context in comments.

1 Comment

apology for late reply, but awesome piece of code, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.