0898-88889999
网站首页 关于天辰平台 天辰注册 天辰动态 天辰登录 天辰开户 天辰APP 在线留言 联系我们
咨询热线
0898-88889999
地址:海南省海口市
邮箱:admin@youweb.com

天辰动态

当前位置: 首页 > 天辰动态

Qt程序主线程执行大量计算 界面卡顿,有什么方法优化?

发布时间:2024-03-12 11:18:28 点击量:

建议读一下

doc.qt.digia.com/qq/qq2

Qt的多线程接口多给力啊、、

从底层到上层都有、、何必非要放到主线程?

核心思想:前后台分离

永远不要用主线程做UI之外的任何事情!

方法一:

使用QThread,把逻辑功能打包到子线程。不要继承重写QThread::run,而是把逻辑功能封装为一个QObject,不要在类里写任何死循环,而是用基于信号槽的事件触发思想进行。

这个类里,const读函数允许直接调用,而会发生修改的比如写函数和控制函数,全部做成信号槽——这样的好处是你不需要做任何线程锁,Qt的信号槽会帮你处理好数据同步操作。但代价是信号槽操作为异步操作

方法二:

只跑一次的操作,比如异步操作一个函数,继承重写QRunnable,然后放进Qt的全局线程池里

方法三:

方法二比较麻烦,还要继承类。更方便的是用QtConcurrent模块,传一个函数指针和对应参数进去,就可以自动完成异步执行

你说主线程执行大量计算导致界面卡顿,有什么方法优化?

首先你必须先要了解Qt的刷新机制

  1. Qt框架最主要的刷新机制来源于事件循环,而事件循环是单线程!单线程!单线程!

2. 你看到界面上所有的控件显示都来源于绘画事件PaintEvent去更新

举个例子

假如你在鼠标点击一个按钮,做了一件很耗时的事情

事件就会卡在你按钮的响应事件函数里面

如果此时控件有更新,但是事件还卡在按钮的响应中

就会导致控件的绘画事件会一直等待

造成你看到界面迟迟不能刷新的卡顿现象


其实你只有看明白这个原理,是有很多办法来规避的

比如把耗时的函数都放到异步去执行

比如开个定时器去循环控件的绘画事件

比如在复杂耗时的函数中插入一些控件的绘画事件

等等

核心就在于你先要了解卡顿的原因

后面就可以按照自己的想法去规避或者解决这些问题


如果你要问我有没有最优解的方案

那我还是有那么一点点建议的

最近用vue比较多

在用得过程中产生一些奇妙的化学反应

说到底界面就是用来显示数据和交互数据的一个媒介

任何数据都可以统称为data

对于data一般来说有两个不可缺少的函数

一个是getData,另一个是setData

一个是用来获取数据显示到界面上,另一个是通过交互去处理数据

其实我一直在思考为什么不把Qt的界面上的控件数据都做成一种映射

就像vue一样,通过在setData里面加入一个信号槽

每次一修改数据,他就会主动通知所有绑定信号槽的控件去更新数据

然后把Qt的事件循环给做成定时的

每60帧就去检测一下有没有控件数据被更新

如果有,就统一把这些需要更新的控件们执行下绘画事件

如果没有,就等待下一次检测

这样的话后台数据处理就不用关心界面刷新的事情

单独开一个线程池去处理所有后台处理数据

通过信号槽去通知子线程有事件到来

需要数据也不用去找界面的控件上面获取

只需要找控件对应绑定的数据就可以

虽然会存在60帧的延迟,但也满足了绝大多数的数据同步要求了

这个只是一个不成熟的猜想

实现起来肯定有一堆技术问题难处理

前端的控件都是标签语言又是树状结构,渲染机制也不同

而Qt的控件都是一个个对象,相互之间都是通过子控件表去维护

检测控件更新遍历就很繁琐,数据更新还需要加锁解锁

想一想就挺麻烦的,还是不祸害你了


成熟的方案也挺多的,最经典就是MVC模式了

Model层,将数据和方法逻辑单独封装好,提供对外的接口

View层,就是界面只负责在Model拿数据显示就可以

Controller层,用来处理用户的交互,转交给Model的方法做处理

把耗时的的逻辑处理部分分包给Model和Controller异步处理

界面拿到数据做渲染就可以了

如果渲染数据比较多,可以在Model帮忙先预处理一下

界面直接拿预处理好的数据显示即可


写得有点没头没脑的

起的太早了,还没睡醒,见谅

1.假的多线程,可以适时调用 QCoreApplication::processEvents(),这样各种状态条都能刷新,比如for里面 i %1000==0时刷一次。

2.真的双线程,用子线程做,主线程进度条。适时emit signal_process(v),刷进度条

3.线程池,比如 QFuture Mapreduce,适合批量密集均衡计算(每个核心预计在差不多的时间完成)。流水线线程池,适合批量密集的非均衡计算,每个事务分为微粒,最多一次处理100个微粒就重新排队,避免阻塞他人。

3.控制刷新速率,子线程不断刷新一个曲线的数据缓存,主线程每秒只读30次。我们做过频谱仪,FFT缓存在后台均衡,主界面的刷新周期是固定的,就是30次。足够了。要刷新的东西是在另一个线程形成了最终产品才显示的。比如你65536点fft,但当前视窗就1024x768,则进行下归并。

真正显示的流量,只要满足肉眼看着花哨不卡顿就行了。

Qt的信号槽、Event、底层线程模型、Concurrent、Qt容器、智能指针、Lambda绑定这些合起来,几乎是无敌的存在,各种计算密集、吞吐密集、计算+吞吐密集、均匀峰值、猝发峰值、平均性能指导优化、峰值性能指导优化、最差性能指导优化,都能应对。

C++Qt就是一个超级乐高,非常棒!

平台注册入口