当前位置:网站首页>Qt多线程的多种方法之一 QThread
Qt多线程的多种方法之一 QThread
2022-07-07 01:11:00 【温逗死】
QThread 似乎是很难的一个东西,特别是信号和槽。以下仅本人学习过程中写的简单案例。
QThread多线程使用方法
QThread类提供了一个与平台无关的管理线程的方法。在Qt中建立线程的主要目的就是为了用线程来处理那些耗时的后台操作,比如大量运算,复制大文件,网络传输等。
使用Qt框架开发应用程序时,使用QThread类可以方便快捷地创建管理多线程。
而多线程之间的通信也可使用Qt特有的“信号-槽”机制实现。
QThread的使用方法有如下两种:
- 继承QThread类
- QObject::moveToThread()
继承QThread方法
第一种方法很简单,也很好理解,写一个类继承QThread类,并重写run()函数,并在主线程中生成一个ChildThread的实例,并调用对象的start()函数。
界面(.h):
#ifndef THREADDLG_H
#define THREADDLG_H
#include <QDialog>
#include <QPushButton>
#include "workthread.h"
#define MAXSIZE 5 //MAXSIZE宏定义了线程的数目
class ThreadDlg : public QDialog
{
Q_OBJECT
public:
ThreadDlg(QWidget *parent = 0);
~ThreadDlg();
private:
QPushButton *startBtn;
QPushButton *stopBtn;
QPushButton *quitBtn;
workThread *myThread[MAXSIZE]; //创建线程指针数组
public slots:
void slotStart(); //槽函数用于启动线程
void slotStop(); //槽函数用于终止线程
};
#endif // THREADDLG_H
界面(.cpp):
#include "threaddlg.h"
#include <QHBoxLayout>
ThreadDlg::ThreadDlg(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("线程"));
startBtn = new QPushButton(tr("开始"));
stopBtn = new QPushButton(tr("停止"));
quitBtn = new QPushButton(tr("退出"));
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(startBtn);
mainLayout->addWidget(stopBtn);
mainLayout->addWidget(quitBtn);
connect(startBtn,SIGNAL(clicked()),this,SLOT(slotStart()));
connect(stopBtn,SIGNAL(clicked()),this,SLOT(slotStop()));
connect(quitBtn,SIGNAL(clicked()),this,SLOT(close()));
}
void ThreadDlg::slotStart()
{
for(int i=0;i<MAXSIZE;i++)
{
myThread[i]=new workThread(); //创建五个线程
}
for(int i=0;i<MAXSIZE;i++)
{
myThread[i]->start(); //启动这五个线程
}
startBtn->setEnabled(false);
stopBtn->setEnabled(true);
}
void ThreadDlg::slotStop()
{
for(int i=0;i<MAXSIZE;i++)
{
myThread[i]->terminate();//结束这五个线程
myThread[i]->wait();//阻塞等待处理结束
}
startBtn->setEnabled(true);
stopBtn->setEnabled(false);
}
ThreadDlg::~ThreadDlg()
{
}
线程类:(.h)
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
class workThread:public QThread
{
public:
workThread();
protected:
void run();
};
#endif // WORKTHREAD_H
若想主线程给子线程传递参数,则可以采用构造函数进行交互数据。
线程类:(.cpp)
#include "workthread.h"
#include <QDebug>
#include <QVector>
workThread::workThread()
{
}
void workThread::run()
{
QVector<int> nums{
1,2,4,3,6,4,2,2,23434,554,232,323,54,66};
int n = nums.size();
bool isChange = false;
while (true) {
for(int i = 1;i<n;i++){
for(int j = 0;j<n-i-1;j++){
if(nums[j]>nums[j+1])
{
int t = nums[j];
nums[j] = nums[j+1];
nums[j+1] = t;
isChange = true;
}
}
if(!isChange){
break;
}
}
for(int &n:nums){
qDebug()<<n<<" ";
}
}
}
QObject::moveToThread
说实话这种方法我没有很理解
- 定义一个普通的QObject派生类FileWorker,然后将其对象move到QThread中。
- 在定义一个转发类也是QObject子类,起名字叫controller,或者叫dummy。将转发类的信号槽和FileWorker类的信号槽关联起来,这样在主线程中调用转发类的槽函数,或者接收信号就OK了。
大概意思是通过转发类,能使得FileWorker类的槽函数妥当的运行在子线程里面。同时也不需要使用QMutex来进行同步,Qt的事件循环会自己自动处理好这个。
总结
推荐做的:
在QThread子类添加信号。这是绝对安全的,并且也是正确的(发送者的线程依附性没有关系)
不应该做的是:
调用moveToThread(this)函数
指定连接类型:这通常意味着你正在做错误的事情,比如将QThread控制接口与业务逻辑混杂在了一起(而这应该放在该线程的一个独立对象中)
在QThread子类添加槽函数:这意味着它们将在错误的线程被调用,也就是QThread对象所在线程,而不是QThread对象管理的线程。这又需要你指定连接类型或者调用moveToThread(this)函数
使用QThread::terminate()函数
不能做的是:
在线程还在运行时退出程序。使用QThread::wait()函数等待线程结束
在QThread对象所管理的线程仍在运行时就销毁该对象。如果你需要某种“自行销毁”的操作,你可以把finished()信号同deleteLater()槽连接起来
参考:https://blog.csdn.net/zb872676223/article/details/22718087
边栏推荐
- 云加速,帮助您有效解决攻击问题!
- 原生小程序 之 input切换 text与password类型
- Industrial Finance 3.0: financial technology of "dredging blood vessels"
- MFC BMP sets the resolution of bitmap, DPI is 600 points, and gdiplus generates labels
- Vscode for code completion
- 目标检测中的损失函数与正负样本分配:RetinaNet与Focal loss
- VScode进行代码补全
- C note 13
- Cf:c. column swapping [sort + simulate]
- Opensergo is about to release v1alpha1, which will enrich the service governance capabilities of the full link heterogeneous architecture
猜你喜欢
Go语学习笔记 - gorm使用 - gorm处理错误 | Web框架Gin(十)
ML's shap: Based on the adult census income binary prediction data set (whether the predicted annual income exceeds 50K), use the shap decision diagram combined with the lightgbm model to realize the
[daily training -- Tencent selected 50] 235 Nearest common ancestor of binary search tree
[云原生]微服务架构是什么?
Go语学习笔记 - gorm使用 - 原生sql、命名参数、Rows、ToSQL | Web框架Gin(九)
Nvisual network visualization
Three level menu data implementation, nested three-level menu data
Jinfo of JVM command: view and modify JVM configuration parameters in real time
If you don't know these four caching modes, dare you say you understand caching?
Introduction to yarn (one article is enough)
随机推荐
软件测试知识储备:关于「登录安全」的基础知识,你了解多少?
yarn入门(一篇就够了)
[shell] clean up nohup Out file
JVM命令之 jstack:打印JVM中线程快照
linear regression
Harmonyos practice - Introduction to development, analysis of atomized services
Jstat of JVM command: View JVM statistics
Wechat applet Bluetooth connects hardware devices and communicates. Applet Bluetooth automatically reconnects due to abnormal distance. JS realizes CRC check bit
老板总问我进展,是不信任我吗?(你觉得呢)
Check point: the core element for enterprises to deploy zero trust network (ztna)
Flask 1.1.4 werkzeug1.0.1 analyse du code source: processus de démarrage
盘点国内有哪些EDA公司?
The boss always asks me about my progress. Don't you trust me? (what do you think)
Detailed explanation of platform device driver architecture in driver development
OpenSergo 即将发布 v1alpha1,丰富全链路异构架构的服务治理能力
关于STC单片机“假死”状态的判别
Interview questions and salary and welfare of Shanghai byte
PTA ladder game exercise set l2-004 search tree judgment
Storage of dental stem cells (to be continued)
Three level menu data implementation, nested three-level menu data