QT多线程——解决因串口数据过多而导致程序界面崩溃的问题

文章介绍了如何使用QT的QThread进行多线程处理,以解决上位机通过串口接收下位机高频数据时出现的界面卡顿和程序崩溃问题。通过创建一个继承自QObject的worker类,在子线程中处理串口数据,然后利用信号槽机制与GUI线程通信,确保界面的流畅性。这种方法提高了程序的稳定性和响应速度。

一 前言:

最近我开发了一个QT上位机应用程序。该应用程序通过串口接收来自下位机的数据,并将下位机处理后的数据结果显示在用户界面上。下位机每隔200毫秒向QT上位机发送一帧包含20字节的数据。然而,在这一过程中,程序经常出现界面卡顿和崩溃的问题。虽然可以通过降低下位机数据发送频率(例如,每1秒发送一帧数据)来避免这一问题,但这种解决方案并不理想。为了更优雅地处理这一问题,我采用了QT的多线程机制——在GUI线程之外,创建了一个专用的子线程来处理串口数据。


二 步骤

2.1 方法描述

​QThread 类提供了一个与平台无关的管理线程的方法。一个 QThread 对象管理一个线程。QThread 的执行从 run() 函数的执行开始,在 Qt 自带的 QThread 类中,run() 函数通过调用 exec() 函数来启动事件循环机制,并且在线程内部处理 Qt 的事件。在 Qt 中建立线程的主要目的就是为了用线程来处理那些耗时的后台操作,从而让主界面能及时响应用户的请求操作。具体操作步骤如下:

  1. 定义一个继承于 QObject 的 worker 类,在 worker 类中定义一个槽函数 doWork(),这个函数中接收和处理串口数据,并将处理好的数据发送给GUI线程。
  2. 在GUI线程的 controller 类中,新建一个 QThread 的对象和 woker 类对象,使用 moveToThread() 方法将 worker 对象的事件循环全部交由 QThread 对象处理。
  3. 建立相关的信号函数和槽函数进行连接,GUI线程发出信号触发 QThread 的槽函数处理串口数据,数据处理完毕后QThread 子线程发送信号触发GUI线程槽函数接收处理好的串口数据。

2.2 代码实现

2.2.1 子线程中

1.新建一个继承与QObject的子线程类:SerialWorker
image-20230614110031377
2.修改serialworker.h
image-20230614110849762
3.修改serialworker.c
image-20230614111637763

2.2.2 GUI线程中

1.修改widget.h
image-20230614112946267
2.修改widget.c
image-20230614120706073


三 总结

经过测试,采用子线程处理串口数据收发操作能够显著提高程序的运行稳定性,并有效解决了因串口数据量过大而导致的界面卡顿问题。
除了创建专门的串口数据处理线程之外,还可以通过异步处理数据的方式来防止界面崩溃。具体做法是,在接收到串口数据后,不立即进行数据处理,而是将数据暂存至队列中,并采用异步机制进行后续处理。这样不仅可以减轻主线程的负担,还能避免因数据处理过程中的延迟而导致的用户界面响应迟缓或崩溃。


参考博客:
QT 中的多线程—moveToThread 篇 - 知乎 (zhihu.com)
Qt子线程、多线程使用串口 QSerialPort QThread QObject_qt 串口多线程_超级大洋葱806的博客-优快云博客

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值