【问题标题】:"The I/O operation has been aborted because of either a thread exit or an application request" on disconnecting serial“由于线程退出或应用程序请求,I/O 操作已中止”断开串行连接
【发布时间】:2015-12-19 10:22:38
【问题描述】:

我正在编写一个程序来从串行读取数据并显示它。有时(不是每次)当我断开串行连接时它会崩溃,但The I/O operation has been aborted because of either a thread exit or an application request 除外。 (我猜这里有问题,即使不是每次都发生)。

这是我阅读连载的方式:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // this line below is where the exception is
    string read = _serialPort.ReadLine().Replace(".", ",").Split('\r')[0];
}

// clicking on a button opens/closes serial
private void button1_Click(object sender, EventArgs e)
{
    if (isSerialConnected)
        disconnectSerial();
    else
        connectSerial();
}

public void connectSerial()
{
    _serialPort.PortName = serialCombobox.SelectedItem.ToString();
    _serialPort.BaudRate = 9600;
    _serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
    _serialPort.Open();

    serialCombobox.Enabled = false;
    connectSerialButton.Text = "disconnect";

    isSerialConnected = true;
}

public void disconnectSerial()
{
   _serialPort.Close();

    serialCombobox.Enabled = true;
    connectSerialButton.Text = "connect";

    isSerialConnected = false;
}

我做错了什么?

【问题讨论】:

  • 这不可能,SerialPort.Close() 调用与 DataReceived 事件处理程序互锁。当事件处理程序仍在运行时,Close() 无法进行。水晶球说您实际上用手猛拉 USB 连接器。永远不要这样做,始终通过安全删除硬件托盘图标。不清楚为什么你这样做,拔掉插头永远不会解决死锁。而是修复你的事件处理程序,永远不要调用 Invoke(),总是 BeginInvoke()。另外请记住,如果您不设置 ReadTimeout 属性,通信不可靠或中断,ReadLine() 是有风险的。
  • @HansPassant 不,我没有拔掉它,我只是在我的应用程序中多次点击连接/断开串行按钮,最终发生异常
  • @HansPassant 并且我没有在我的处理程序中使用 Invoke() ,我只使用 BeginInvoke 在主线程中运行一些代码,但无论如何,如果我要注释掉这段代码,例外是还是扔了。

标签: c# exception exception-handling serial-port


【解决方案1】:

您在事件处理程序中从串行端口读取数据。来自SerialPort.ReadLine()

默认情况下,ReadLine 方法会阻塞,直到收到一行。

所以当你关闭串口时,你可能还在等待接收一条线。但是如果端口关闭则无法接收数据,因此会抛出异常,因为无法再接收一行。

【讨论】:

  • 那我应该怎么处理呢?我想我可以将它包装在 try/catch 语句中,并且在 catch 块中什么都不做,但有些事情告诉我这不是应该这样做的。
  • 在您的示例中,无论如何您都不会使用 ReadLine 的结果,因此可以使用空捕获。您可能不想要UnhandledException 事件。如果您能够以有用的方式处理异常,那总是更好。我至少建议记录异常以帮助将来进行诊断。但是,上面 Hans Passant 的评论很有趣。这表明我的回答是错误的。或者其他地方可能存在错误(在驱动程序中?)。
  • 其实后来用了,我只是注释掉了,看看ReadLine()那一行是不是真的是异常的原因
【解决方案2】:

我已经以这种方式进行了更改,现在这有点工作。

try
{
    read = _serialPort.ReadLine().Replace(".", ",").Split('\r')[0];
}
catch (System.IO.IOException error)
{
    return;
}
catch (System.InvalidOperationException error)
{
    return;
}

发生了 2 种错误,IOException 和问题标题中的消息,以及 InvalidOperationException,消息“端口已关闭”。在这两种情况下,我们只会返回而不处理数据。

我不确定它是否应该这样做,但无论如何,它有点工作。

【讨论】:

    【解决方案3】:

    当您在您的SerialDataReceivedEventHandler 中从SerialPort.ReadLine() 获取数据时 你必须检查串口是否打开。

    例如:

    if (!_serialPort.IsOpen)
    {
      return;
    }
    
    string read = _serialPort.ReadLine().Replace(".", ",").Split('\r')[0];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-03
      • 2023-03-23
      • 2014-02-17
      • 1970-01-01
      • 2022-01-23
      • 2012-09-01
      相关资源
      最近更新 更多