You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WPF串口报错:因线程退出或应用请求终止I/O操作

问题分析与解决方案

核心问题原因

报错The I/O operation has been aborted because of either a thread exit or an application request本质是异步读取未完成时串口被强制关闭,结合代码来看,主要存在两个关键问题:

  1. Stop按钮的逻辑完全写反,导致关闭串口的时机错误
  2. 异步读取流程中未正确处理"主动停止"场景下的异常,将正常中止误判为错误

另外,长期运行的程序突然失效,也可能和系统更新导致的串口驱动变化、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());
            }
        }
    }
}

额外排查建议

  1. 检查串口驱动:更新设备的串口驱动,Windows更新可能导致旧驱动兼容性问题
  2. 确认COM端口:重启设备后COM端口号可能变更,在设备管理器中核实当前端口
  3. 权限验证:以管理员身份运行程序,避免串口访问权限不足
  4. 资源占用检查:使用串口调试工具确认无其他程序占用目标COM端口

内容的提问来源于stack exchange,提问作者Cosmin Popa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:56:02