title: C# Drawing multiple charts in real time in a separate thread
body: <p>I have a acquistion device that reads data and adds it to the buffer. This is done in a separate thread. Once this data is dequeued, I set up a delegate that raise the event OnDataRead().</p>
  
  <p>In my signal monitor, when the event is received I want to plot the data in multiple charts (16 in total). Since I have 16 charts, instead of updating the charts every time new data is received, I add them in a buffer for the data and the timestamps. The charts are updated in a separate thread every 100ms by reading the data stored in the buffer and the timestamps. However, when I plot the data, some charts stop adding data and in all charts, lot of values are not displayed. Is this a bad approach? What would be a better approach or what should I change to make it work?</p>
  
  <p>I have 256samples/second*16channels.</p>
  
  <p>This is what I get
  <a href="https://i.stack.imgur.com/XhQ0p.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XhQ0p.png" alt="signal monitor (16 channels)"></a></p>
  
  <p>This is what I would expect but for all 16 channels</p>
  
  <p><a href="https://i.stack.imgur.com/Fb4gY.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Fb4gY.png" alt="enter image description here"></a></p>
  
  <pre><code> public void OnDataRead(object source, DataEventArgs e)
      {
           if ((e.rawData.Length &gt; 0) &amp;&amp; (!_shouldStop))
              {
                  for (int sampleIdx = 0; sampleIdx &lt; e.rawData.Length; sampleIdx++)
                  {
                      lock (_bufferRawData)
                          // Append data
                          _bufferRawData.Add(e.rawData[sampleIdx]);
  
                      lock (_bufferXValues)
                          _bufferXValues.Add(DateTime.Now);
  
                  }
      }
  
   private void AddDataThreadLoop()
          {
              while (!_shouldStop)
              {
                  chChannels[1].Invoke(addDataDel);
  
                  Thread.Sleep(100); //sleeps for 100ms
              }
          }
  
   private void AddData()
          {
  
              // Copy data stored in lists to arrays
              if (_bufferRawData.Count &gt; 0)
              {
                  float[] rawData;
                  lock (_bufferRawData)
                  {
                      rawData = _bufferRawData.ToArray();
                      _bufferRawData.Clear();
                  }
                  DateTime[] xValues;
                  lock (_bufferXValues)
                  {
                      xValues = _bufferXValues.ToArray();
                      _bufferXValues.Clear();
                  }
  
                  // Add new data points for the selected channel chart
                  int channelIdx = 0; 
  
                  for (int sampleIdx = 0; sampleIdx &lt; rawData.Length -1; sampleIdx++)
                  {
                      // Calculate the channel where the smaple corersponds
                      channelIdx = sampleIdx % (_numChannels + 1);
  
                     foreach (Series ptSeries in chChannels[channelIdx].Series)
                              // Add new datapoint to the corresponding chart (x, y, chartIndex, seriesIndex)
                              AddNewPoint(xValues[sampleIdx], rawData[sampleIdx], channelIdx, ptSeries);
  
                  }
              }
          }
  
  public void AddNewPoint(DateTime timeStamp, float yValue, int chartIDx, System.Windows.Forms.DataVisualization.Charting.Series ptSeries)
      {
  
          //Add datapoint
          ptSeries.Points.AddXY(timeStamp.ToOADate(), yValue);
  
          // Remove old datapoints if needed
          double removeBefore = timeStamp.AddSeconds((double)(8) * (-1)).ToOADate();
          while (ptSeries.Points[0].XValue &lt; removeBefore)
          {
              ptSeries.Points.RemoveAt(0);
          }
  
          // Modify minimum and maximum for new samples
          chChannels[chartIDx].ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
          chChannels[chartIDx].ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddSeconds(10).ToOADate();
          chChannels[chartIDx].ChartAreas[0].AxisY.Maximum = _yMax;
          chChannels[chartIDx].ChartAreas[0].AxisY.Minimum = -_yMax;
  
          chChannels[chartIDx].Invalidate();
      }
  
  private void btnPlay_Click(object sender, EventArgs e)
  {
       //Create thread
       //define a thread to add values into chart
       ThreadStart addDataThreadObj = new ThreadStart(AddDataThreadLoop);
       addDataRunner = new Thread(addDataThreadObj);
       addDataDel += new AddDataDelegate(AddData);
  
       //Start thread
       addDataRunner.Start();
      }
  </code></pre>
  
  <p><strong>EDIT1:</strong>
  chChanels is a list of charts where each element correspond to one of the charts.
       public List chChannels;</p>
  
  <p><strong>EDIT2</strong>
  After changing the lock for this, all charts are updated. However lot of samples for each chart are still not updated.</p>
  
  <pre><code> lock (_bufferRawData) {
          for (int sampleIdx = 0; sampleIdx &lt; e.rawData.Length; sampleIdx++)
          {
             // Append data
             _bufferRawData.Add(e.rawData[sampleIdx]);
             _bufferXValues.Add(DateTime.Now);
          }
      }
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/Rzr9t.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Rzr9t.png" alt="enter image description here"></a></p>