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