一、创建多线程的方式
QT创建(使用)多线程的方式有三种。
- 直接创建QThread 对象,重写run方法,最后调用start方法启动线程。
- 通过调用QObject类提供的moveToThread方法实现
- 线程池
(一)方式一:
如果需要向run传入参数,或者返回执行结果,可以通过信号和槽机制实现
- mywork.h
#ifndef MYWORK_H
#define MYWORK_H
#include <QObject>
#include <QThread>
/**
* @class mywork.h
*
* @brief 工作线程
*
*
* @author: lihua
* @date: 2022-10-25 15:53
*/
class MyWork : public QThread
{
Q_OBJECT
public:
explicit MyWork(QThread *parent = nullptr);
signals:
//信号由子线程发出,主线程接收(子线程返回执行结果给主线程)
void signalWork(int result);
public slots:
//信号由主线程发出,子线程接收(主线程传入参数给子线程)
void slotWork(int num);
// QThread interface
protected:
void run();
private:
int num = 0;
};
#endif // MYWORK_H
- mywork.cpp
#include "mywork.h"
#include <QDebug>
MyWork::MyWork(QThread *parent) : QThread(parent)
{
}
void MyWork::slotWork(int num)
{
//调用槽函数
qDebug()<< "子线程的槽函数被调用"<<num;
this->num = num;
}
/**
* @brief 主线程传一个初始值num给子线程,子线程在num的基础上加100
*
* @param run没有参数,num是通过槽函数获取的
*
* @return run没有返回值将计算结果通过槽函数返回给主线程
*/
void MyWork::run()
{
qDebug()<< "运行子线程<<" << QThread::currentThread();
//主线程给一个初始值num
int num = this->num;
int result = num +100;
//发出信号,订阅了此信号的订阅者的槽函数会被回调,将计算结果通过槽函数返回给主线程
qDebug()<< "结果:"<<result;
emit signalWork(result);
}
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "mywork.h"
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
//子线程
MyWork *thread;
// 计算结果
int result;
signals:
//信号
void signalMain(int num);
public slots:
//槽函数
void slotMain(int result);
};
#endif // MAINWINDOW_H
- mainwindow.cpp
#include "mainwindow.h"
#include "mywork.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug()<< QThread::currentThread();
thread = new MyWork();
//订阅signalMain信号,并指定回调函数。
connect(this,&MainWindow::signalMain,thread,&MyWork::slotWork);
//订阅signalWork信号,并指定回调函数
//connect(thread,&MyWork::signalWork,this,&MainWindow::slotMain); 也可以用lamda实现
connect(thread,&MyWork::signalWork,this,[=](int result){
this->result = result;
qDebug()<< "result="<<this->result;
});
//发出一个信号,将10通过槽函数slotWork传递给run
emit signalMain(10);
thread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slotMain(int result)
{
this->result = result;
qDebug()<< "result="<<this->result;
}
(二)方式二:
更改此对象及其子对象的线程关联。如果对象具有父对象,则无法移动该对象。事件处理将在targetThread中继续。
如果targetThread为零,则此对象及其子对象的所有事件处理都将停止。
请注意,对象的所有活动计时器都将重置。计时器首先在当前线程中停止,然后在targetThread中重新启动(以相同的间隔)。因此,在线程之间不断移动对象会无限期地延迟计时器事件。
在更改线程关联之前,QEvent::ThreadChange事件被发送到此对象。您可以处理此事件以执行任何特殊处理。请注意,任何发布到此对象的新事件都将在targetThread中处理。
警告:此函数不是线程安全的;当前线程必须与当前线程关联性相同。换句话说,此函数只能将对象从当前线程“推”到另一个线程,不能将对象从任意线程“拉”到当前线程
。文章来源:https://www.toymoban.com/news/detail-500536.html
- mywork1.h
#ifndef MYWORK1_H
#define MYWORK1_H
#include <QObject>
class MyWork1 : public QObject
{
Q_OBJECT
public:
explicit MyWork1(QObject *parent = nullptr);
//工作函数
void work();
signals:
void curNumber(int num);
public slots:
};
#endif // MYWORK1_H
- mywork1.cpp
#include "mywork1.h"
#include <QThread>
#include <QDebug>
MyWork1::MyWork1(QObject *parent) : QObject(parent)
{
}
void MyWork1::work()
{
qDebug()<< "子线程对象地址:"<<QThread::currentThread() ;
int num = 0;
while(1)
{
emit curNumber(num++);
if(num == 1000)
{
break;
}
QThread::usleep(1);
}
qDebug() << "run() 执行完毕, 子线程退出...";
}
- 核心代码
void MainWindow::testThread()
{
QThread *thread = new QThread();
MyWork1 *work = new MyWork1();
//注意这个方法是QObject提供的,将对象从当前线程“推”到另一个线程运行
work->moveToThread(thread);
thread->start();
//不能直接调用,直接调用还是主线程运行
//work->work();
//通过槽机制运行才能将对象交给targetThread运行。
connect(ui->pushButton,&QPushButton::clicked,work, &MyWork1::work);
connect(work,&MyWork1::curNumber,this,[=](int num){
ui->textBrowser->setText(QString::number(num));
});
}
(三)方式三:
QThreadPool类管理QThreads的集合。
QThreadPool管理和重新设计单个QThread对象,以帮助减少使用线程的程序中的线程创建成本。每个Qt应用程序都有一个全局QThreadPool对象,可以通过调用globalInstance()来访问该对象。
要使用QThreadPool线程之一,请将QRunnable子类化并实现run()虚拟函数。然后创建该类的对象并将其传递给QThreadPool::start()文章来源地址https://www.toymoban.com/news/detail-500536.html
#include "mywork2.h"
#include <QDebug>
#include <QThread>
MyWork2::MyWork2()
{
}
void MyWork2::run()
{
qDebug()<< "线程池方式使用多线程。"<<QThread::currentThread();
}
/**
* @brief 线程池测试
*
* @param
* @param
*
* @return
*/
void MainWindow::testThreadPool()
{
//获取线程池,同时设置最大线程数。
QThreadPool::globalInstance()->setMaxThreadCount(2);
MyWork2 *work = new MyWork2();
QThreadPool::globalInstance()->start(work);
}
到了这里,关于QT——C++ 多线程05的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!