WPF中的SerialPort引发I/O异常

本文关键字:异常 引发 中的 SerialPort WPF | 更新日期: 2023-09-27 18:00:14

我正在开发一个非常简单的程序(VS2010中的C#WPF应用程序),该程序显示SerialPort中的数据并显示在TextBox上。这个程序在正常情况下运行良好。但是,当用户打开一个连接,收集一些数据,关闭它,然后再次打开它,并这样做几个周期时,程序最终会抛出一个异常:

"由于线程退出或应用程序请求,I/O操作已中止。"[ReadLine()中发生I/O异常]

有时程序会给我抛出一个异常;有时程序会挂起。以下是我的代码:

/* Click to Open ComPort */
private void PortOpen_Click(object sender, RoutedEventArgs e)
{
    if (!serialPort1.IsOpen)
    {
        serialPort1.PortName = "COM1";
        serialPort1.BaudRate = 9600;
        serialPort1.ReceivedBytesThreshold = 1;
        serialPort1.NewLine = "'r'n";
        serialPort1.Parity = Parity.None;
        serialPort1.StopBits = StopBits.One;
        serialPort1.DataBits = 8;
        serialPort1.Handshake = Handshake.None;
        serialPort1.Open();
        serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Receive);
    }
}
/* Receive data from ComPort */
private void Receive(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    if (serialPort1.IsOpen)
    {
        try
        {
            string1 = serialPort1.ReadLine(); /* This is where I/O Exception occurred */
            Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(DisplayText), string1);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}
private void DisplayText(string string1)
{
    textBox1.Text = string1;
}
/* Close ComPort */
private void PortClose_Click(object sender, RoutedEventArgs e)
{
    if (serialPort1.IsOpen)
    {
        serialPort1.Close();
    }            
}

以下是我在过去40个小时里对桌面的尝试,但没有取得任何进展的总结:

  1. 我尝试在Open()Close()之前和之后添加Thread.Sleep(3000)。我开始感到非常沮丧,以至于我把Thread.Sleep放在每一行之间。我认为这将为一些未完成的后台工作留出足够的时间。不能解决问题
  2. 我试过Zach Saw的帖子。在博客上留下的许多评论都是非常正面的。我尝试了这种方法,甚至将确切的代码复制粘贴到我的代码中。不能解决问题。一篇很长的帖子浪费了我半天的时间
  3. 金·汉密尔顿在这里谈到了这些问题。建议使用CCD_ 5而不是CCD_。尝试并仍然坚持同样的问题
  4. 有一个非常好的商业SerialPort库Franson SerialTools,它相当便宜,无论我打开()或关闭()串行端口多少时间和多快,都能很好地工作,没有任何错误。然而,他们已经停止了开发,他们拥有的库只用于Form应用程序,而不是WPF。API中的某些参数只接受Forms.Control.太糟糕了。还有其他商业产品,但要么价格过高,要么不提供免费试用,所以在购买之前我不知道它是否有效

是否有人让.NET串行端口工作,并多次检查错误(打开()和关闭(),即使没有传入数据)?

WPF中的SerialPort引发I/O异常

当你打开端口时,你会添加事件处理程序,当你关闭时,我认为你应该删除它。

尝试这样做:

private void PortClose_Click(object sender, RoutedEventArgs e)
{
    if (serialPort1.IsOpen)
    {
        serialPort1.DataReceived -= Receive;
        serialPort1.Close();
    }            
}

希望这能解决问题。

我想对ReadLine的阻塞调用会被UI线程对Close的调用中断。发现这个错误有什么错?我希望它能发生。

@Reniuz解决方案对我也没有帮助。事实上,我根本不明白它怎么会有帮助,很明显,正如@Hans Passant评论的那样,在取消订阅活动时,DataReceived可能已经在进行中了。我对此的解决方案是在DataReceived事件中取消订阅,只要在需要取消订阅时发出一个标志,并在DataReceived事件中检查它。

public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
// Brief:   Handle data received event
{
  // Read the data
  // ~~~~~~~~~~~~~
  // Check for unsubscribe
  // ~~~~~~~~~~~~~~~~~~~~~
  if (bStopDataRequested)
  {
    serialPort1.DataReceived -= DataReceivedHandler;  // Unsubscribe to DataReceived event
    // Only then close the port
  }
}