【问题标题】:IO operation aborted error thrown while reading serial port读取串口时抛出 IO operation aborted 错误
【发布时间】:2014-02-13 20:05:07
【问题描述】:

我们正在尝试读取由使用 .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 事件中写入的串行端口上的数据,如下面的代码 sn-p 所示:

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
}

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

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

【问题讨论】:

  • 当串口忙于接收数据时关闭串口可能会出现此异常。您有意为此编写了代码,调用了 Close() 和 Dispose() 方法。不要不要这样做。如果您的代码在初始化时调用 InitializeSerialPort(),那么这是一个错误。改为抛出 InvalidOperationException 以便诊断此错误。
  • 您好汉斯,感谢您的快速回复。仅供参考,InitializeSerialPort 方法仅在应用程序启动时调用一次以初始化串行端口对象。因此,不可能在已经处理的对象上读取串行端口。

标签: c# .net serial-port ioexception


【解决方案1】:

我们可以通过将代码锁定在 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 方法中的整段代码,以确保从串行端口接收到的新数据的新执行不会开始,除非旧的读取尚未完成。在反复试验的基础上实施此代码后,问题得到解决。希望这对遇到此类问题的其他人也有帮助。

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2018-02-05
    • 2016-09-13
    • 1970-01-01
    相关资源
    最近更新 更多