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

C#程序串口读取过程中打开新窗体出现冻结问题求解决方案

问题核心原因

  1. SerialPort.DataReceived 事件默认运行在后台工作线程,所有窗体创建、显示/隐藏、控件修改等UI操作必须在UI线程执行,你当前直接在后台线程触发窗体创建和显示,已经引发线程死锁,是窗体冻结的根因。
  2. processData方法逻辑存在缺陷:当队列数据不足14字节时,空的byteArray会被强制遍历赋值,引发空引用异常,未捕获的异常会导致程序无响应。
  3. 用到的Queue是非线程安全类,多线程读写时会出现未知异常。

修复方案

1. 把UI操作封送到UI线程执行

修改processData中打开新窗体的逻辑,通过主窗体的Invoke方法将操作调度到UI线程:

if (bits13[2]&&reentrant==0)
{
    reentrant = 1;
    // 新增UI线程调度
    this.Invoke((Action)(() => 
    {
        Form1 formita = new Form1(this);
        formita.Show();
    }));
}

2. 修复Form1的Load逻辑

Form的Load事件本身就运行在UI线程,不需要额外调用Invoke,直接修改为:

private void Form1_Load(object sender, EventArgs e)
{
    mainy2.Hide();
}

3. 修正processData的执行逻辑

所有数据处理逻辑必须放在队列数据足够的判断分支内,数据不足时直接返回:

public void processData()
{
    byte[] byteArray = new byte[14];
    if (recievedData.Count <= 13)
    {
        // 数据不足直接返回
        return;
    }
    for (int i = 0; i < byteArray.Length; i++)
    {
        byteArray[i] = recievedData.Dequeue();
    }
    // 后续所有数据转换、判断、Writing调用逻辑都放在这里执行
    // ... 原有处理逻辑 ...
}

4. 替换为线程安全的队列

将非线程安全的Queue替换为ConcurrentQueue,避免多线程并发读写异常:

// 替换原有Queue定义
private ConcurrentQueue<byte> recievedData = new ConcurrentQueue<byte>();

对应修改出队逻辑:

// 原有byteArray[i] = recievedData.Dequeue();替换为
recievedData.TryDequeue(out byte currentByte);
byteArray[i] = currentByte;

优化建议

原代码中14次BitArray转换逻辑完全重复,可以通过循环实现,大幅精简代码量,降低出错概率。


内容的提问来源于stack exchange,提问作者Miguel Rodmen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:54:03