By drawing some real time graphs, C # forms

I would like to get a preview of the 16 channels of my A / C, and I need a refresh rate of 25-40 Hz (update every 25-40 ms). I made several combinations of flows and timers, but I achieved satisfactory performance for only 4 diagrams. After expanding the range of diagrams for updating, the frame rate of added graphs was about 0.5 / s. I applied a fast line chart.
 I applied a timer to receive new data from A / C every 20 ms. After some tests, it seems that adding a separate thread to process each chart that sleeps for a certain time and then updates the chart is inefficient (at least the way I did it).
 Therefore, the question arises: how to efficiently process multiple diagrams.
Below I present the most important parts of the code.

    System.Timers.Timer tim = new System.Timers.Timer(20);
    System.Threading.Thread[] t;
    int HighChan = 15;
    //button which runs the preview, executed once
    private void previewB_Click(object sender, EventArgs e)
    {                                            
        t = new System.Threading.Thread[HighChan + 1];
        for (int i = 0; i <HighChan+1; i++)
        {                    
            charts[i].Series.SuspendUpdates();
            //run a separate thread for each chart
            t[i] = new System.Threading.Thread(new ParameterizedThreadStart(updatePlot));
            t[i].Start(i);                    
        }

        //run timer to get new data with tim.interval                    
        tim.Stop();               
        tim.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);           
        tim.Start();                                
    }

    ushort[] ADData_prev;
    //get new data from A/C every tim.interval
    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields
        // I also tried to suspend and resume threads t from this place but unsuccessfully
    }


    //update the chart with new data
    void updatePlot(object chart_info)
    {          
        int i = (int)chart_info;

        while(true)
        {
                //wait for new data to read
                Thread.CurrentThread.Join(20);

                charts[i].Invoke(new Action(delegate()
                { charts[i].ResetAutoValues(); }));

                // I skipped some conditions to make code clearer                              
                //remove old point and add new one
                charts[i].Invoke(new Action(delegate()
                {
                    charts[i].Series[0].Points.RemoveAt(0);
                    charts[i].Series[0].Points.AddY(ADData_prev[i]);
                }));                     

                charts[i].Invoke(new Action(delegate()
                {
                    charts[i].Series.ResumeUpdates();
                    charts[i].Series.Invalidate();
                    charts[i].Series.SuspendUpdates();
                }));

          }
    }

Update:
1. I moved the functionality of updatePlot () to the onTimedEvent timer, so now it looks like this:

    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields

        charts[0].Invoke(new Action(delegate()
        {

           for (int i = 0; i < HighChan + 1; i++)
           {
               //charts[i] stuff here
           }
        }
    }

2.I decided to change the bool variable to onTimedEvent, which allows you to draw diagrams once, each timer goes in cycles until the (true) loop in updatePlot ():

    private void previewB_Click(object sender, EventArgs e)
    {                                            
        for (int i = 0; i <= HighChan; charts[i++].Series.SuspendUpdates()) ;
        t = new System.Threading.Thread(updatePlot);
        t.Start();

        //run timer to get new data with tim.interval                    
        tim.Stop();               
        tim.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);           
        tim.Start();                                
    }

    bool entry = false;
    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields
        entry = true;            
    }

    void updatePlot()
    {
       while(true)
       {
          if(entry)
          {
               charts[0].Invoke(new Action(delegate()
               {
                  for (int i = 0; i < HighChan + 1; i++)
                  {
                     //charts[i] stuff here
                  }
               }
          entry = false;
          }
       }
    }

These decisions made only a slight improvement. Unfortunately, in both cases, the charts do not update quickly enough. In addition, the first 8 of the array of charts [] are updated quickly, and the last 8 have a frame rate of about 0.5 Hz, which is rather strange for me that they do not behave the same.


Update 2:

, 20-40 . , , (A/C Fs = 1k ). , , .

, , .
, nr ( ) 6, ti ( ) 20 , (np) = 50 , . , np 100, 1-4 , 5 6 . nr = 6, ti = 20, np = 250, 1-3 , 4-6 0,1fps.

nr = 10, ti = 20, np = 50, 1-6 , nr = 6, 7-8 , 9-10 - 1fps. nr = 10, ti = 20, np = 100, 1-6 , nr = 6 ( 1-3 ), 7-8 9- 10, 0.1fps.

nr = 16, ti = 20, np = 50, 1-8 nr = 10, 8 - 0.05fps - .

, , , / , , Thread.Sleep(), Threed.CurrentThread.Join(), Timers, async, . , , , 16 .
.

+4
1

, , . , - , .

, , 20 , Invoke , Action. .

+1

Source: https://habr.com/ru/post/1531914/


All Articles