耗时IO对象移到子线程,防止UI卡顿

调用QObject::moveToThread,把m_SerialPort的 "线程归属" 从主线程改为m_serialThread;

此后m_SerialPort的所有槽函数(如果连接了信号)都会在m_serialThread中执行,而非主线程;

注意:移线程的前提是m_SerialPort无父对象(如果有父对象,moveToThread会失效),这也是代码中new QSerialPort()不指定父对象的原因。

cpp 复制代码
Q_DECLARE_METATYPE(CheckInfoList)
CommSerialPort::CommSerialPort()
{
    m_SerialPort = new QSerialPort();//不指定父对象
    //注册自定义元类型(跨线程信号槽传递数据用)
    qRegisterMetaType<QList<std::pair<int, int>>>("QList<std::pair<int,int>>");
    qRegisterMetaType<CheckInfoList>("QList<std::pair<int,int>>");

    // 创建工作线程
    m_serialThread = new QThread();
    // 注意:不要连接 finished 到 deleteLater,因为我们在析构函数中手动管理线程生命周期
    
    // 只将串口对象移到工作线程(不要移动 this)
    m_SerialPort->moveToThread(m_serialThread);
    m_serialThread->start();
    
    // 初始化发送时间记录器
    m_lastSendTime.start();

    // 自动重连:定时器在主线程中(因为 this 在主线程)
    m_reconnectTimer = new QTimer(this);
    m_reconnectTimer->setInterval(m_reconnectIntervalMs);
    connect(m_reconnectTimer, &QTimer::timeout, this, &CommSerialPort::onReconnectTimeout);
    
    // 串口错误信号连接(跨线程连接,使用 Qt::QueuedConnection)
    connect(m_SerialPort, &QSerialPort::errorOccurred, this, &CommSerialPort::onErrorOccurred, Qt::QueuedConnection);
    connect(m_SerialPort, &QSerialPort::errorOccurred, this, &CommSerialPort::handleSerialTimeout, Qt::QueuedConnection);

    // m_sendTimer = new QTimer(this);
    // m_sendTimer->setInterval(m_sendIntervalMs);
    // connect(m_sendTimer, &QTimer::timeout, this, &CommSerialPort::SendBufferData);
    // m_sendTimer->start();

    m_commAlertManager = new AlertDialogManager();
}

qt官方:QTimer is a subclass of QObject and as such, it must live in the thread where it was created. It is not safe to access a QTimer from another thread. (QTimer是QObject子类,必须归属创建它的线程;从其他线程访问QTimer是不安全的)

m_reconnectTimer自动重连定时器的onReconnectTimeout重连逻辑已经通过connect将m_reconnectTimer和CommSerialPort绑定了 ,如果后续出现串口错误信号连接没有使用QueuedConnection,会让导致不在同一个线程访问QTimer ,qt没有对访问不同线程中的QTimer设置线程安全 ,可能会导致定时器定时不准,导致后续定时器可能失效

Qt 对这种跨线程操作QTimer的行为不做线程安全保护:

轻量问题:定时器定时不准、启动 / 停止指令无响应(比如调用stop()但定时器还在跑);

严重问题:主线程和子线程同时操作定时器的内部状态,引发内存竞态,程序崩溃。

相关推荐
ndsc_d2 小时前
2026年有哪些好用的AI UI设计工具?主流工具功能和适用场景对比
前端·人工智能·ui·ai·设计师·ai ui·ai ui工具
DM今天肝到几点?3 小时前
OpenAI 向全量用户开放 GPT-6 与 Intelligent UI:聊天框正在变成工作台
gpt·ui·chatgpt
FII工业富联科技服务20 小时前
Intelligent UI重构工业软件交互:从固定界面到动态生成式交互
人工智能·ui·重构
FII工业富联科技服务1 天前
从大模型到自主运营:Intelligent UI如何成为工业AI的新入口
人工智能·ui
qq_252959971 天前
ChatGPT突然长出“可操作界面”:GPT-6 Intelligent UI让答案变成计算器、地图和小游戏
gpt·ui·chatgpt
兰亭妙微UI设计公司1 天前
兰亭妙微ui设计公司分享:从零搭建网站设计:3 个核心维度,少走设计弯路
ui
Cx330❀2 天前
Qt 多线程深度解析:从底层原理到 UI 线程与同步实战
开发语言·qt·ui·搜索引擎·性能优化·图形渲染
传奇开心果编程2 天前
【声明式UI实用开发技术学与练】第5课 表单处理:受控与非受控
ui·移动开发·开发范式·编程框架·声明式ui
传奇开心果编程2 天前
【声明式UI开发实用技术学与练】第9课 派生状态与计算
ui·移动开发·ux·编程框架·声明式ui
ZARD9962 天前
Codex 连接 Figma:让 AI 读取 Figma UI 设计稿数据
ui·figma·codex