C# WPF串口报错:因线程退出或应用请求终止I/O操作
问题分析与解决方案
核心问题原因
报错The I/O operation has been aborted because of either a thread exit or an application request本质是异步读取未完成时串口被强制关闭,结合代码来看,主要存在两个关键问题:
- Stop按钮的逻辑完全写反,导致关闭串口的时机错误
- 异步读取流程中未正确处理"主动停止"场景下的异常,将正常中止误判为错误
另外,长期运行的程序突然失效,也可能和系统更新导致的串口驱动变化、COM端口权限或资源占用有关。
具体修复步骤
1. 修正Stop按钮逻辑
原代码中stopButton的条件if (!isListening)完全颠倒,应在正在监听时执行停止操作:
- 先标记停止状态
isListening = false - 关闭串口前确保异步读取流程能正确终止
- 处理文件写入和状态重置
2. 优化异步读取的异常处理
主动关闭串口时,EndRead会抛出中止类IOException,这属于正常流程,无需弹窗提示,只需捕获后终止监听即可。
3. 线程安全与资源优化
- 使用
StringBuilder替代字符串拼接,避免线程安全问题和性能损耗 - 延迟初始化串口实例,避免提前占用系统资源
修改后的完整代码
using System; using System.IO; using System.IO.Ports; using System.Text; using System.Windows; namespace InfoCOM { public partial class MainWindow : Window { private bool isListening = false; private SerialPort mySerialPort; private readonly StringBuilder resultBuilder = new StringBuilder(); public MainWindow() { InitializeComponent(); // 延迟初始化串口,避免提前占用资源 mySerialPort = new SerialPort(); } private void stopButton(object sender, RoutedEventArgs e) { if (isListening) { isListening = false; try { if (mySerialPort.IsOpen) { mySerialPort.Close(); } File.WriteAllText("text.txt", resultBuilder.ToString()); MessageBox.Show("数据已写入text.txt"); resultBuilder.Clear(); } catch (Exception ex) { MessageBox.Show($"停止时出错: {ex.Message}"); } } } private void Listen() { if (!mySerialPort.IsOpen || !isListening) return; byte[] buffer = new byte[65536]; mySerialPort.BaseStream.BeginRead(buffer, 0, buffer.Length, ar => { try { if (!isListening || !mySerialPort.IsOpen) { return; } int bytesRead = mySerialPort.BaseStream.EndRead(ar); if (bytesRead > 0) { string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); resultBuilder.Append(receivedData); Dispatcher.Invoke(() => { Nume.Text = resultBuilder.ToString(); }); // 继续监听 Listen(); } } catch (IOException ioEx) { // 过滤主动中止的正常异常 if (!ioEx.Message.Contains("aborted")) { Dispatcher.Invoke(() => MessageBox.Show($"I/O错误: {ioEx.Message}")); } isListening = false; } catch (Exception ex) { Dispatcher.Invoke(() => MessageBox.Show($"意外错误: {ex.Message}")); isListening = false; } }, null); } private void startButton(object sender, RoutedEventArgs e) { try { if (mySerialPort.IsOpen) { mySerialPort.Close(); } mySerialPort.PortName = "COM4"; mySerialPort.BaudRate = 9600; mySerialPort.Parity = Parity.None; mySerialPort.StopBits = StopBits.One; mySerialPort.DataBits = 8; mySerialPort.Handshake = Handshake.None; mySerialPort.Open(); isListening = true; Listen(); } catch(Exception ex) { MessageBox.Show("启动失败!"); MessageBox.Show(ex.ToString()); } } } }
额外排查建议
- 检查串口驱动:更新设备的串口驱动,Windows更新可能导致旧驱动兼容性问题
- 确认COM端口:重启设备后COM端口号可能变更,在设备管理器中核实当前端口
- 权限验证:以管理员身份运行程序,避免串口访问权限不足
- 资源占用检查:使用串口调试工具确认无其他程序占用目标COM端口
内容的提问来源于stack exchange,提问作者Cosmin Popa
相关产品推荐
相关产品推荐

