文章目录
- 1. 概述
- 2. UML 类的关系图
- 3. 代码:
- 4. 运行结果及说明
- 5. 结语
1. 概述
任何继承于QThread的线程都是通过继承 QThread 的run函数来实现多线程的,因此,必须重写QThread的run函数,把复杂逻辑写在QThread的run函数中。然后在主线程中调用 start() 函数来启动子线程。
2. UML 类的关系图
3. 代码:
首先写 MyThread 类,该类继承于 QThread 类,该类中自定义了信号和槽,并且重写了 run 函数,头文件如下:
//
// MyThread.h
//
#ifndef DEL2_MYTHREAD_H
#define DEL2_MYTHREAD_H
#include <QThread>
#include <QDebug>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject* parent = nullptr);
signals:
void myThreadSignal(const int); // 自定义发送的信号
public slots:
static void myThreadSlot(int); // 自定义槽函数
protected:
void run() override ;
};
#endif //DEL2_MYTHREAD_H
//
// mythread.cpp
//
#include "mythread.h"
MyThread::MyThread(QObject* parent)
: QThread(parent)
{
}
//2. 新线程中的 0x4684
void MyThread::run()
{
qDebug() << __FUNCTION__ << " Thread ID: " << QThread::currentThreadId() << "\n";
emit myThreadSignal(100); // 发送结束信号
exec();
}
//3. 主线程中的 0x5120
void MyThread::myThreadSlot(const int val)
{
qDebug() << __FUNCTION__ << " Thread ID: " << QThread::currentThreadId() << ", val: " << val <<"\n";
}
在 ThreadController 类中实现 MyThread 的调用
//
// threadcontroller.h
//
#ifndef THREADCONTROLLER_H
#define THREADCONTROLLER_H
#include <QObject>
#include "mythread.h"
class ThreadController : public QObject
{
Q_OBJECT
public:
explicit ThreadController(QObject *parent = nullptr);
~ThreadController() override ;
public slots:
static void handleResults(int result); // 处理子线程执行的结果
signals:
void operate(const int); // 发送信号,触发线程
private:
MyThread* _myThread ;
};
#endif // THREADCONTROLLER_H
//
// WorkerController.cpp
//
#include "threadcontroller.h"
ThreadController::ThreadController(QObject *parent) : QObject(parent)
{
_myThread = new MyThread ;
connect(_myThread, &MyThread::myThreadSignal, this, &ThreadController::handleResults);
// 该线程结束时销毁
connect(_myThread, &QThread::finished, this, &QObject::deleteLater);
connect(this, &ThreadController::operate, _myThread, &MyThread::myThreadSlot);
// 启动该线程
_myThread->start();
// 当前线程挂起 3s
QThread::sleep(3);
//3. --- 先执行当前槽函数,再执行run中槽函数
emit operate(99);
}
ThreadController::~ThreadController()
{
_myThread->quit();
_myThread->wait();
}
//4. 主线程中的 0x5120
void ThreadController::handleResults(const int result)
{
qDebug() << __FUNCTION__ << " Thread ID:" << QThread::currentThreadId() << ", last result: " << result;
}
接下来就是 main 函数,主函数中我们新建一个 Controller 对象,开始执行:
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "threadcontroller.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << __FUNCTION__ << " Thread ID:" << QThread::currentThreadId() << '\n' ;
ThreadController c ;
return a.exec(); // 进入事件循环
}
4. 运行结果及说明
注意:
- 只有 run() 中的才是新线程,其余都是主线程!
- QThread::sleep(3); 使用后,当前主线程挂起 3 秒,而子线程中 run() 继续执行,休眠结束后才会运行主线程的槽函数!
5. 结语
子类化 QThread 的方法,就是重写了 QThread 中的 run() 函数,在 run() 函数中定义需要的工作。这样的结果是,我们自定义的子线程调用 start() 函数后,便开始执行 run() 函数。如果在自定义的线程类 MyThread 中定义相关的槽函数,那么这些槽函数不会由子类化的QThread 自身事件循环所执行,而是由该子线程的拥有者(一般都是主线程)来执行。
而 qt 的线程设计不是希望通过继承去实现多线程,而是希望线程也是作为一个对象可以直接使用,也就是 QObject的moveToThread方法
本文也只是初步的学习,没有关注于线程的释放和创建,进一步使用可以参考: Qt使用多线程的一些心得
参考: QT 中的多线程—继承 QThread 篇