当前位置:网站首页>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
边栏推荐
- Understand the deserialization principle of fastjson for generics
- Ctfshow-- common posture
- linear regression
- Deep clustering: joint optimization of depth representation learning and clustering
- POI excel export, one of my template methods
- SAP Spartacus checkout 流程的扩展(extend)实现介绍
- yarn入门(一篇就够了)
- Mac version PHP installed Xdebug environment (M1 version)
- 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
- Harmonyos practice - Introduction to development, analysis of atomized services
猜你喜欢

【日常训练--腾讯精选50】235. 二叉搜索树的最近公共祖先

Deep clustering: joint optimization of depth representation learning and clustering

C note 13

Detailed explanation of platform device driver architecture in driver development

Introduction to the extension implementation of SAP Spartacus checkout process

JVM命令之- jmap:导出内存映像文件&内存使用情况

Go语学习笔记 - gorm使用 - 原生sql、命名参数、Rows、ToSQL | Web框架Gin(九)

Three level menu data implementation, nested three-level menu data
Interview questions and salary and welfare of Shanghai byte

Reading notes of Clickhouse principle analysis and Application Practice (6)
随机推荐
[InstallShield] Introduction
那些自损八百的甲方要求
R language [logic control] [mathematical operation]
Deep clustering: joint optimization of depth representation learning and clustering
关于STC单片机“假死”状态的判别
Career experience feedback to novice programmers
Digital IC interview summary (interview experience sharing of large manufacturers)
980. Different path III DFS
Solve pod install error: FFI is an incompatible architecture
CMD permanently delete specified folders and files
Nvisual network visualization
PTA 天梯赛练习题集 L2-004 搜索树判断
盘点国内有哪些EDA公司?
【日常训练--腾讯精选50】292. Nim 游戏
Peripheral driver library development notes 43: GPIO simulation SPI driver
Vscode for code completion
cf:C. Column Swapping【排序 + 模擬】
如何在Touch Designer 2022版中设置解决Leap Motion不识别的问题?
Mac version PHP installed Xdebug environment (M1 version)
如果不知道这4种缓存模式,敢说懂缓存吗?