当前位置:网站首页>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
边栏推荐
猜你喜欢

Introduction to yarn (one article is enough)

职场经历反馈给初入职场的程序员

mac版php装xdebug环境(m1版)

Mac version PHP installed Xdebug environment (M1 version)
![[InstallShield] Introduction](/img/df/4522d06510ff918d00659b8358368f.jpg)
[InstallShield] Introduction

SAP ABAP BDC (batch data communication) -018

10W word segmentation searches per second, the product manager raised another demand!!! (Collection)

Why does the data center need a set of infrastructure visual management system

The solution of a simple algebraic problem

POI excel export, one of my template methods
随机推荐
cf:C. Column Swapping【排序 + 模拟】
搞懂fastjson 对泛型的反序列化原理
[daily training -- Tencent selected 50] 235 Nearest common ancestor of binary search tree
Loss function and positive and negative sample allocation in target detection: retinanet and focal loss
EMMC打印cqhci: timeout for tag 10提示分析与解决
Dc-7 target
Digital IC interview summary (interview experience sharing of large manufacturers)
Reptile exercises (III)
PTA 天梯赛练习题集 L2-004 搜索树判断
jvm命令之 jcmd:多功能命令行
Go language learning notes - Gorm use - Gorm processing errors | web framework gin (10)
Career experience feedback to novice programmers
PTA 天梯赛练习题集 L2-002 链表去重
Sequential storage of stacks
Convert numbers to string strings (to_string()) convert strings to int sharp tools stoi();
Subghz, lorawan, Nb IOT, Internet of things
驱动开发中platform设备驱动架构详解
绕过open_basedir
Detailed explanation of platform device driver architecture in driver development
VScode进行代码补全