2017-09-06 14 views
0

私は、グラフの配列を計算し、グラフをプロットするサブを持っています。 計算用に2つのスレッド(getArrayForGraph())とプロットグラフ用に2つのスレッドがあります。動的更新配列のためのvb.netチャート

今、アレイが非常に長く(10 000 000)、すべてのプロセスが非常に遅くなるため、サイドアレイの更新機能に沿ってプロットするグラフが必要です。

私はどのようにグラフを利用できるようになるとすぐにグラフを更新し始めますか?またはパフォーマンスの問題を解決する最善の方法です。

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 
+0

getArrayForGraphはどのくらいの頻度で呼び出されますか? – djv

+0

ユーザーが更新ボタンをクリックすると、与えられた入力に対してグラフがリフレッシュされますので、一度言います – user1565283

+0

主な問題は、MSChartが多くのデータポイントを処理できないことです。あなたはそれをまったくプロットすることはできますか?たとえばミリ秒単位でデータを集計し、各ミリ秒の平均データを最初の/平均/前回のミリ秒までプロットする必要があるかもしれません。 – djv

答えて

0

完全な例です。これはBackgroundWorkerを使用して作業を実行し、更新するためにUIに信号を送ります。また、データを集約します。 MSChartは多くの点を扱うことができず、2.私のディスプレイは1920ピクセルの幅しかないので、もっと表示しようとする必要はありません。この例では、5k(10M/2k)ポイントごとに1ポイントをプロットします。これはx:最新の時刻、y:平均値です。もしあなたが好きであれば、平均的な時間を取ることもできますが、これはきれいです。

情報が不足しているため、特定の変数が含まれていません。しかし、あなたはそれがどのように動作し、それがあなたの環境で動作するかを考えなければなりません。

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 
+0

遅刻の返事のためのお詫び、コードの素晴らしい一片、ありがとう! – user1565283

関連する問題