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

WPF下C#串口监视器DataReceived事件处理及交互问题求助

已解决:WPF串口监视器UI更新异常与命令发送无返回问题

我最近在开发一个集成到基于winPcap的以太网通信工具里的WPF串口监视器(用来替代HyperTerminal或TeraTerm),需求很明确:读取单片机输出的菜单和命令列表并显示到TextBox,等加载完成后发送flash-命令烧写板载FPGA。开发过程中踩了两个大坑——更新TextBox时触发异常,发送命令后收不到返回结果,现在已经全部搞定,把修复后的完整代码分享给有需要的朋友:

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for SerialMonitor.xaml
    /// </summary>
    public partial class SerialMonitor : Window
    {
        // VARIABLES
        public SerialPort comPort = new SerialPort();

        public SerialMonitor()
        {
            // initialization
            InitializeComponent();
            scanPorts();
        }

        private void scanPorts()
        {
            textBoxIndata.Clear();
            string[] ports = SerialPort.GetPortNames();
            foreach (string port in ports)
            {
                comboBoxPorts.Items.Add(port);
            }
        }

        private void openComBtn_Click(object sender, RoutedEventArgs e)
        {
            comPort.Parity = Parity.None;
            comPort.DataBits = 8;
            comPort.ReadTimeout = 500;
            comPort.StopBits = StopBits.One;

            // 修复重复的空值判断
            if (comboBoxPorts.SelectedItem != null && !string.IsNullOrEmpty(comboBoxBaud.Text))
            {
                comPort.PortName = comboBoxPorts.SelectedItem.ToString();
                if (int.TryParse(comboBoxBaud.Text, out int baudRate))
                {
                    comPort.BaudRate = baudRate;
                    try
                    {
                        // Open port and add the event handler on datareceived
                        comPort.Open();
                        comPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                        label1.Content = "COM PORT OPEN";
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                }
                else
                {
                    MessageBox.Show("请输入有效的波特率");
                }
            }
        }

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            // 读取串口接收的数据
            string indata = sp.ReadExisting();
            // 调用UI更新方法,切换到UI线程
            updateUI(indata);
        }

        // 修复UI更新的跨线程问题
        private void updateUI(string s)
        {
            // WPF中必须通过Dispatcher在UI线程更新控件
            if (textBoxIndata.Dispatcher.CheckAccess())
            {
                textBoxIndata.AppendText(s);
                // 自动滚动到最新内容
                textBoxIndata.ScrollToEnd();
            }
            else
            {
                textBoxIndata.Dispatcher.Invoke(() => updateUI(s));
            }
        }

        // 添加发送命令的按钮事件(假设XAML中有名为sendFlashBtn的按钮)
        private void sendFlashBtn_Click(object sender, RoutedEventArgs e)
        {
            if (comPort.IsOpen)
            {
                // 发送烧写命令,注意加换行(根据单片机协议调整)
                comPort.WriteLine("flash-");
            }
            else
            {
                MessageBox.Show("请先打开串口");
            }
        }

        // CLOSE AND EXIT BUTTONS
        private void closeComBtn_Click(object sender, RoutedEventArgs e)
        {
            if (comPort.IsOpen)
            {
                comPort.Close();
                label1.Content = "COM PORT CLOSED";
            }
        }

        private void exitBtn_Click(object sender, RoutedEventArgs e)
        {
            if (comPort.IsOpen)
            {
                comPort.Close();
            }
            this.Close();
        }
    }
}

核心修复点说明

  • 跨线程UI更新:SerialPort的DataReceived事件在后台线程触发,直接操作TextBox会抛出线程异常,用Dispatcher.Invoke切换到UI线程执行更新是关键
  • 完善数据接收逻辑:实现了DataReceivedHandler读取串口数据,并用AppendText替代直接赋值Text,避免覆盖原有内容
  • 命令发送优化:添加了专门的命令发送按钮事件,用WriteLine发送命令(如果单片机需要特定结束符,比如回车换行,可根据协议调整),确保发送后能被单片机正确识别并返回结果
  • 输入验证增强:增加了波特率的数值验证,避免无效输入导致的异常

内容的提问来源于stack exchange,提问作者Francesco Steinwender

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:41:09