title: Drawing several charts in real time, C# forms
body: <p>I'd like to get a preview from 16 channels of my A/C and I need the refresh rate at 25-40Hz (update every 25-40ms). I made few combinations of threads and timers but I achieved satisfying performance only for at most 4 charts. After extending the range of charts to refresh, the frame rate of added charts was about 0.5/s. I applied fastline chart.  <br>
   I applied a timer to get new data from A/C every 20ms. After some tests it looks that adding a separate thread to deal with each chart, which sleeps for a given time and then updates the plot is not efficient (at least in the manner I did it). <br>
   So the question is: how to efficiently handle with multiple charts.  <br>
  Below I present most important parts of the code.</p>
  
  <pre><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 &lt;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();
                  }));
  
            }
      }
  </code></pre>
  
  <hr>
  
  <p>Update: <br>
  1.I have moved the functionality of updatePlot() to timer's onTimedEvent so now it looks like that:</p>
  
  <pre><code>    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 &lt; HighChan + 1; i++)
             {
                 //charts[i] stuff here
             }
          }
      }
  </code></pre>
  
  <p>2.I decided to change the bool variable in onTimedEvent which allows to draw charts once, every timer's tick in while(true) loop in updatePlot():</p>
  
  <pre><code>    private void previewB_Click(object sender, EventArgs e)
      {                                            
          for (int i = 0; i &lt;= 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 &lt; HighChan + 1; i++)
                    {
                       //charts[i] stuff here
                    }
                 }
            entry = false;
            }
         }
      }
  </code></pre>
  
  <p>These solutions made only very slight improvement. Unfortunately, still, in both cases, charts aren't refreshed quickly enough. Additionally, first 8 from the charts[] array are refreshing fast, while the last 8 have the frame rate of about 0.5 Hz what is quite strange for me that they not behave in the same way.</p>
  
  <hr>
  
  <p>Update 2: <br></p>
  
  <p>As in the first post, I need to redraw charts every 20-40ms. When I draw only one plot  I can achieve this frame rate so it is not a matter of data collection time (the A/C works in background with Fs=1k Hz). Maybe binding queue to a chart made it faster but not to much.
  <br><br>
  I'll describe more precisely what has happened in the performance tests which I conducted.<br>
  So, when I limit nr (number of charts to refresh) to 6, update them with ti (time interval) 20ms, so they store number of points (np) = 50 at a moment, they all run smooth. But, when I change the np to 100, only charts 1-4 run smooth, when 5 slows down very much and 6 almost stops.
  When nr = 6, ti = 20, np = 250, the charts 1-3 run smoothm while charts 4-6 run like 0.1fps.</p>
  
  <p>When nr = 10, ti = 20, np = 50, the charts 1-6 behave in the same way as in nr=6 case, while charts 7-8 surprisingly run smooth and 9-10 are like 1fps.
  When nr = 10, ti = 20, np = 100, the charts 1-6 behave in the same way as in nr=6 case (so only charts1-3 run smooth), while charts 7-8 still run smooth and 9-10 are like 0.1fps.</p>
  
  <p>When nr = 16, ti = 20, np = 50, charts 1-8 behave like in nr=10 case and the other 8 are like 0.05fps or something.</p>
  
  <p>Whichever method I use, with single thread, multiple threads, single/multiple Invoke, Queue binding, Thread.Sleep(), Threed.CurrentThread.Join(), Timers, async the result is always more less the same. Honestly I don't know what can be the reason why I can't get real time data preview on 16 fastline charts. <br>
  I'd be thankful for any advice.</p>