【发布时间】:2015-10-14 21:26:33
【问题描述】:
我有一个读取数据并将其添加到缓冲区的采集设备。这是在一个单独的线程中完成的。一旦这些数据出队,我就会设置一个委托来引发 OnDataRead() 事件。
在我的信号监视器中,当收到事件时,我想在多个图表中绘制数据(总共 16 个)。因为我有 16 个图表,所以我没有在每次收到新数据时都更新图表,而是将它们添加到数据和时间戳的缓冲区中。通过读取存储在缓冲区中的数据和时间戳,图表每 100 毫秒在一个单独的线程中更新。但是,当我绘制数据时,一些图表停止添加数据,并且在所有图表中,很多值都没有显示。这是一个不好的方法吗?什么是更好的方法或者我应该改变什么才能使它起作用?
我有 256 个样本/秒*16 个通道。
这是我所期望的,但对于所有 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 是一个图表列表,其中每个元素对应一个图表。 公共列表 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?恐怕除非您提供一个可以实际编译和测试的示例,否则任何尝试帮助您都很难走得很远。
标签: c# multithreading forms charts real-time