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