概述
通常在程序中需要同时做好几件事情,这时不可避免的会涉及到多线程的学习,QT学习过程中亦是如此,而QT
中提供了 QThread
,因为涉及到信号与槽,线程的使用也有些变化。在QThread
的文档中有两种使用方法。
文章目录- 概述
- 一.QObject::moveToThread()
- 二.QObject::moveToThread() 的使用例子
一.QObject::moveToThread()
这个是第一种方式,直接调用 QObject::moveToThread()
函数,将继承自 QObject
的对象移到线程里面。此时该对象的 槽函数运行在另一个线程里面。 也就是说,当有信号绑定到该对象的槽函数的时候,并发送信号,该槽函数就运行在另一个线程里,否则该函数仍然运行在对象所在的线程中.
下面是使用代码片段:
代码语言:javascript复制 QThread workThread;
Worker worker = new Worker();
worker->moveToThread(&workThread);
workThread.start();
二.QObject::moveToThread()的使用例子
下面将参照文档,举一个例子来说明线程的使用并验证上述说法(可直接先看下面结果,再看过程):
1. 首先先写一个继承自QObject
的Worker
类(为了使用信号和槽).
- 在worker.h 中声明 doWork 槽函数,以及完成信号
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
Worker(QString name , QObject *parent = nullptr);
signals:
void resultReady(const QString &resultReady); //工作完成信号
public slots:
void doWork(const QString ¶meter); //工作函数
private:
QString name;
};
#endif // WOKER_H
- 在worker.cpp 中实现 doWork 槽函数
#include "worker.h"
#include <QDebug>
#include <QThread>
Worker::Worker(QObject *parent) : QObject(parent)
{
}
Worker::Worker(QString name , QObject *parent )
{
this->name = name;
}
void Worker::doWork(const QString ¶meter)
{
qDebug()<<"当前Worker线程ID:"<<QThread::currentThreadId()
<<endl<<name "正在" parameter<<endl;
emit resultReady(name parameter "完成");
}
2. 写一个控制Woker
线程的 Boss
类
- 在
Boss.h
中实现
#ifndef BOSS_H
#define BOSS_H
#include <QObject>
#include <QThread>
#include "worker.h"
class Boss : public QObject
{
Q_OBJECT
public:
explicit Boss(QObject *parent = nullptr);
~Boss();
void order2(const QString order); //用于测试是否使用了线程
signals:
void order(const QString order); //用于测试是否使用了线程
public slots:
void handleResult(const QString result);
private:
QThread workThread; //worker 线程
Worker *worker; //worker 对象指针
};
#endif // BOSS_H
- 在
Boss.cpp
中实现
#include "boss.h"
#include <QDebug>
Boss::Boss(QObject *parent) : QObject(parent)
{
worker = new Worker("A");
worker->moveToThread(&workThread);
connect(&workThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Boss::order, worker, &Worker::doWork); //用信号和槽的方式调用doWork()函数
connect(worker, &Worker::resultReady, this, &Boss::handleResult);
workThread.start();
}
Boss::~Boss()
{
workThread.quit();
workThread.wait();
}
void Boss::handleResult(const QString result)
{
qDebug()<<"Boss got it :"<<result<<endl;
}
void Boss::order2(const QString order)
{
qDebug()<<"order2:";
worker->doWork(order); //直接调用
}
3. 最后实现main.cpp
#include <QCoreApplication>
#include <boss.h>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"当前Boss线程ID:"<<QThread::currentThreadId()<<endl;
Boss *boss = new Boss();
boss->order("整理资料(order)");//用信号触发槽函数的方式
boss->order2("整理资料(order2)");//直接调用函数的方式
return a.exec();
}
4. 结果:
从上面可以看出:
order2
是通过直接调用doWork
的函数,该函数会直接执行在调用对象所在线程order
是通过信号触发doWork
函数,工作在新的线程中。
- 使用
moveToThread
总结: 1. worker 对象的函数要工作在其他线程,用通过信号和槽的方式进行调用
下一篇文章将继续写关于QThread 的另一种使用方法