当前位置:网站首页>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
边栏推荐
- Reading notes of Clickhouse principle analysis and Application Practice (6)
- Go语学习笔记 - gorm使用 - gorm处理错误 | Web框架Gin(十)
- Cf:c. column swapping [sort + simulate]
- 目标检测中的损失函数与正负样本分配:RetinaNet与Focal loss
- Web authentication API compatible version information
- Convert numbers to string strings (to_string()) convert strings to int sharp tools stoi();
- JVM命令之 jinfo:实时查看和修改JVM配置参数
- ML之shap:基于adult人口普查收入二分类预测数据集(预测年收入是否超过50k)利用shap决策图结合LightGBM模型实现异常值检测案例之详细攻略
- Flinksql read / write PgSQL
- [InstallShield] Introduction
猜你喜欢
R language [logic control] [mathematical operation]
从“跑分神器”到数据平台,鲁大师开启演进之路
[InstallShield] Introduction
每秒10W次分词搜索,产品经理又提了一个需求!!!(收藏)
生活中的开销,怎么记账合适
PTA 天梯赛练习题集 L2-004 搜索树判断
职场经历反馈给初入职场的程序员
如何在Touch Designer 2022版中设置解决Leap Motion不识别的问题?
The boss always asks me about my progress. Don't you trust me? (what do you think)
[daily training -- Tencent selected 50] 235 Nearest common ancestor of binary search tree
随机推荐
Jinfo of JVM command: view and modify JVM configuration parameters in real time
Chain storage of stack
OpenSergo 即将发布 v1alpha1,丰富全链路异构架构的服务治理能力
CTFshow--常用姿势
Classic questions about data storage
JVM命令之 jinfo:实时查看和修改JVM配置参数
软件测试知识储备:关于「登录安全」的基础知识,你了解多少?
Dc-7 target
Go语学习笔记 - gorm使用 - gorm处理错误 | Web框架Gin(十)
【FPGA教程案例13】基于vivado核的CIC滤波器设计与实现
Bat instruction processing details
Deep clustering: joint optimization of depth representation learning and clustering
How much do you know about clothing ERP?
Mac version PHP installed Xdebug environment (M1 version)
3428. 放苹果
Reading notes of Clickhouse principle analysis and Application Practice (6)
Introduction to the extension implementation of SAP Spartacus checkout process
Senior programmers must know and master. This article explains in detail the principle of MySQL master-slave synchronization, and recommends collecting
Win configuration PM2 boot auto start node project
Mysql-centos7 install MySQL through yum