我有一個讀取數據並將其添加到緩衝區的設備。這是在一個單獨的線程中完成的。一旦這些數據出列,我就設置了一個引發事件OnDataRead()的委託。C#在單獨的線程中實時繪製多個圖表
在我的信號監視器中,當收到事件時,我想繪製多個圖表中的數據(共16個)。由於我有16個圖表,而不是每次收到新數據時更新圖表,所以我將它們添加到數據和時間戳記的緩衝區中。通過讀取存儲在緩衝區中的數據和時間戳,每隔100ms在一個單獨的線程中更新圖表。但是,當繪製數據時,有些圖表會停止添加數據,並且在所有圖表中,很多值不會顯示。這是一個壞方法嗎?什麼是更好的方法,或者我應該改變以使其工作?
我有256samples /秒* 16channels。
這是我所期望的,但對所有16個信道
public void OnDataRead(object source, DataEventArgs e)
{
if ((e.rawData.Length > 0) && (!_shouldStop))
{
for (int sampleIdx = 0; sampleIdx < 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 > 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 < 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 < 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();
}
EDIT1: chChanels是圖表,其中的列表每個元素對應於其中一個圖表。 public List chChannels;
EDIT2 爲此更改鎖定後,將更新所有圖表。然而,每個圖表的很多樣本仍未更新。
lock (_bufferRawData) {
for (int sampleIdx = 0; sampleIdx < e.rawData.Length; sampleIdx++)
{
// Append data
_bufferRawData.Add(e.rawData[sampleIdx]);
_bufferXValues.Add(DateTime.Now);
}
}
什麼是chChannels?恐怕除非你提供一個實際可以編譯和測試的例子,否則任何試圖幫助你都很困難。 –