当前位置:网站首页>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
边栏推荐
- Jstat pour la commande JVM: voir les statistiques JVM
- Type de texte de commutation d'entrée et de mot de passe de l'applet natif
- 一名普通学生的大一总结【不知我等是愚是狂,唯知一路向前奔驰】
- Bypass open_ basedir
- JVM命令之- jmap:导出内存映像文件&内存使用情况
- Flask 1.1.4 werkzeug1.0.1 analyse du code source: processus de démarrage
- 改变ui组件原有样式
- Reptile exercises (III)
- 如果不知道这4种缓存模式,敢说懂缓存吗?
- 话说SQLyog欺骗了我!
猜你喜欢
Detailed explanation of platform device driver architecture in driver development
[云原生]微服务架构是什么?
POI excel export, one of my template methods
[InstallShield] Introduction
Go language learning notes - Gorm use - native SQL, named parameters, rows, tosql | web framework gin (IX)
Apple CMS V10 template /mxone Pro adaptive film and television website template
mac版php装xdebug环境(m1版)
驱动开发中platform设备驱动架构详解
Go语学习笔记 - gorm使用 - 原生sql、命名参数、Rows、ToSQL | Web框架Gin(九)
DC-7靶机
随机推荐
Bat instruction processing details
Red hat install kernel header file
How to improve website weight
谈fpga和asic的区别
一名普通学生的大一总结【不知我等是愚是狂,唯知一路向前奔驰】
原生小程序 之 input切換 text與password類型
【FPGA教程案例13】基于vivado核的CIC滤波器设计与实现
【日常训练--腾讯精选50】235. 二叉搜索树的最近公共祖先
Peripheral driver library development notes 43: GPIO simulation SPI driver
[solved] record an error in easyexcel [when reading the XLS file, no error will be reported when reading the whole table, and an error will be reported when reading the specified sheet name]
SAP Spartacus checkout 流程的扩展(extend)实现介绍
jvm命令之 jcmd:多功能命令行
Check point: the core element for enterprises to deploy zero trust network (ztna)
EMMC print cqhci: timeout for tag 10 prompt analysis and solution
每秒10W次分词搜索,产品经理又提了一个需求!!!(收藏)
解决pod install报错:ffi is an incompatible architecture
[daily training -- Tencent selected 50] 292 Nim games
如何在Touch Designer 2022版中设置解决Leap Motion不识别的问题?
SAP ABAP BDC (batch data communication) -018
Flask1.1.4 Werkzeug1.0.1 源码分析:启动流程