读取串口时抛出IO操作中止错误

时间:2014-01-23 10:26:10

标签: c# .net serial-port ioexception

我们正在尝试使用.Net串口类读取连接到串口的外部设备(本例中为称重秤)写入的数据。

首先我们初始化串口如下:

InitializeSerialPort()
{
   if ((serialPort != null) && (serialPort.IsOpen))
        {
            serialPort.Close();
            serialPort.Dispose();
            serialPort = null;
        }

        serialPort = new SerialPort("COM2", 9600, Parity.None, 8,
                                    StopBits.One) { Handshake = Handshake.None };
        serialPort.DataReceived += serialPort_DataReceived;
        serialPort.NewLine = "\r";
}

我们正在使用后台工作线程通过在串行端口上发送命令(通过称重秤来理解)来连续轮询设备。一旦我们发送命令,连接到串行端口的设备就会响应响应输出。我们调用SerialPort类的ReadLine API来获取设备在DataReceived事件中写入的串行端口上的数据,如下面的代码片段所示:

private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
    try
        {
            data = serialPort.ReadLine();
        }
        catch(System.IO.IOException ex)
        {
            //since serial port reading threw an error so there is no value to be parsed hence exit the function.
            return;
        }
//if no error then parse the data received
}

我正在使用System.IO.Ports.SerialPort类.Net framework 4.0。我可以看到很多人在其他论坛上发布此问题,但没有具体解决方案。他们中的一些人将.Net串口类称为bug,至今尚未由Microsoft修复。提到此错误的论坛之一是here

我也尝试过发布here的解决方案但没有任何帮助。如果其他任何人遇到此问题或其解决方案,我需要一些输入。

1 个答案:

答案 0 :(得分:0)

我们能够通过将代码锁定在serialPort_DataReceived方法中来解决这个问题。

Object lockObject = new Object();
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    lock(lockObject)
    {
        try
        {
            data = serialPort.ReadLine();
        }
        catch(System.IO.IOException ex)
        {
            //since serial port reading threw an error so there is no value to be parsed hence exit the function.
            return;
        }
    }
    //if no error then parse the data received
}

我们设置了轮询间隔,以便将连接在串口上的设备轮询为10秒。可能在serialPort_DataReceived方法中存在的整个代码有时需要超过10秒。我们无法准确地确定这一事实,因为每次都不会发生这种事实。

因此,我们使用C#中的lock关键字将整段代码锁定在serialPort_DataReceived方法中,以确保从串口接收的新数据的新执行不会启动,除非较旧的读数没有'完了。在试错的基础上实现此代码后问题得到解决。希望如果遇到这样的问题,这也有助于其他人。