winform中接收SerialPort控件的数据并使用Chart控件显示

最近因为TinyOS课中讲到无线通信模块的部分,要求是写一个winform用于接收数据并使用chart显示。

遇到了曾经遇到的问题,当时没有时间仔细研究,这次决定彻底把他解决。

实时显示的时候chart控件会报集合已修改的错误。

(~Y2L}R4%4AV[TYA][EOZC3

这时,chart的区域会变成一个红叉,并且除了重启程序以外无法修复。

我写了一个会报错的最简样例

//error
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Random mrandom = new Random();
    chart1.Series[0].Points.Clear();
    for (int i = 0; i < 50; i++)
        chart1.Series[0].Points.AddY(mrandom.Next(20));
}

首先,我怀疑这个错误是因为处理数据耗时过多产生的,于是我写了一段使用timer快速添加删除数据的代码

private void timer1_Tick(object sender, EventArgs e)
{
    Random mrandom = new Random();
    chart1.Series[0].Points.Clear();
    for (int i = 0; i < 50; i++)
        chart1.Series[0].Points.AddY(mrandom.Next(20));
}

运行很稳定,没有报错。

我怀疑是数据量不够大,又接了一个1e9次的循环,窗体变的非常卡,但是依旧很稳定,没有报错。

既然快速添加删除不会导致报错,那么真的就只是跨线程修改导致的问题了。

于是我为chart加上了锁

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    lock (chart1)
    {
        Random mrandom = new Random();
        chart1.Series[0].Points.Clear();
        for (int i = 0; i < 50; i++)
            chart1.Series[0].Points.AddY(mrandom.Next(20));
    }
}

可是,chart仍然很快就挂了。

这只能说明serialport的datareceive事件开了一个不安全的线程,所以我们不能把chart的处理放在datereceive中。

解决方案:timer是一个安全的线程,我们在datareceive中只处理数据,然后调用timer更新chart控件即可。

最终效果很稳定,没有再产生chart崩溃的现象。

发表评论

电子邮件地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据