QT学习之如何使用Qthread(moveToThread方法)

2022-04-27 17:01:28 浏览数 (1)

概述

通常在程序中需要同时做好几件事情,这时不可避免的会涉及到多线程的学习,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. 首先先写一个继承自QObjectWorker类(为了使用信号和槽).

  • 在worker.h 中声明 doWork 槽函数,以及完成信号
代码语言:javascript复制
#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 &parameter); //工作函数

private:
    QString name;
};

#endif // WOKER_H
  • 在worker.cpp 中实现 doWork 槽函数
代码语言:javascript复制
#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 &parameter)
{
    qDebug()<<"当前Worker线程ID:"<<QThread::currentThreadId()  
    <<endl<<name   "正在"  parameter<<endl;
    emit resultReady(name   parameter "完成");
 }

2. 写一个控制Woker线程的 Boss

  • Boss.h 中实现
代码语言:javascript复制
#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 中实现
代码语言:javascript复制
#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

代码语言:javascript复制
#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. 结果:

从上面可以看出:

  1. order2 是通过直接调用doWork 的函数,该函数会直接执行在调用对象所在线程
  2. order 是通过信号触发doWork 函数,工作在新的线程中。
  • 使用moveToThread总结: 1. worker 对象的函数要工作在其他线程,用通过信号和槽的方式进行调用

下一篇文章将继续写关于QThread 的另一种使用方法

0 人点赞