QThread简单测试理解

该博客探讨了Qt中使用QThread进行多线程操作的方法,包括创建Worker对象并在子线程中运行,以及如何处理信号槽通信。同时,文章详细解释了对象在没有事件循环的线程中的生命周期管理,特别是`deleteLater`的使用和事件处理。
摘要由CSDN通过智能技术生成
#ifndef QTHREADTEST_H
#define QTHREADTEST_H

#include <QObject>
#include <QThread>

// method 1
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void resultReady(const QString& result);
public slots:
    void slotDoWork(const QString& param);

protected:
    bool event(QEvent *e) Q_DECL_OVERRIDE;
};

class Controller : public QObject {
    Q_OBJECT
public:
    explicit Controller(QObject *parent=0);
    ~Controller();

    void doSomething(const QString& param);
public slots:
    void slotHandleResult(const QString &result);
signals:
    void operate(const QString &param);

private:
    QThread worker_thread_;
};

// method 2
class WorkerThread : public QThread {
    Q_OBJECT
public:
    WorkerThread(QObject *parent = 0);
    ~WorkerThread();

protected:
    void run() Q_DECL_OVERRIDE;
    bool event(QEvent *e) Q_DECL_OVERRIDE;

signals:
    void resultReady(const QString& result);
public slots:
    void slotThreadFinished();
};

class Controller2 : public QObject {
    Q_OBJECT
public:
    Controller2(QObject *parent = 0);
    void doSomething();

public slots:
    void slotHandleResult(const QString &result);
};

#endif // QTHREADTEST_H
#include "qthreadtest.h"
#include <QDebug>
#include <QEvent>

Worker::Worker(QObject *parent) :
    QObject(parent)
{
}

// By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread
void Worker::slotDoWork(const QString &param) {
    QString result("done");

    qDebug() << "worker thread id: " << QThread::currentThreadId() << ", then begin sleep 5 secs...";
    QThread::sleep(5);

    emit resultReady(result);
}

bool Worker::event(QEvent *e) {
    if (e->type() == QEvent::DeferredDelete) {
        qDebug() << "thread id: " << QThread::currentThreadId() << ", DeferredDelete";
    }
    return QObject::event(e);
}

Controller::Controller(QObject *parent) : QObject(parent) {
    Worker *worker = new Worker;
    worker->moveToThread(&worker_thread_);
    connect(&worker_thread_, &QThread::finished, worker, &QObject::deleteLater);
    connect(this, &Controller::operate, worker, &Worker::slotDoWork);
    connect(worker, &Worker::resultReady, this, &Controller::slotHandleResult);
    worker_thread_.start();
}

Controller::~Controller() {
    worker_thread_.quit();
    worker_thread_.wait();
}

void Controller::doSomething(const QString& param) {
    emit operate(param);
}

void Controller::slotHandleResult(const QString &result) {
    qDebug() << "thread id: " << QThread::currentThreadId() << ", " << result;
}

///
// WorkerThread & Controller2
/*
void QObject::deleteLater()
{
    QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
...
bool QObject::event(QEvent *e)
{
    switch (e->type()) {
    ....
    case QEvent::DeferredDelete:
        qDeleteInEventHandler(this);
        break;
    ....
    }
}
...
void qDeleteInEventHandler(QObject *o)
{
    delete o;
}
*/
WorkerThread::WorkerThread(QObject *parent) : QThread(parent) {

}

WorkerThread::~WorkerThread() {
    qDebug() << "no event loop, thread id: " << QThread::currentThreadId() << ", ~WorkerThread";
}

void WorkerThread::run() {
    QString result("done");

    qDebug() << "worker thread id: " << QThread::currentThreadId() << ", then begin sleep 5 secs...";
    QThread::sleep(5);

    emit resultReady(result);
}

// 如果在没有event loop的thread使用, 那么thread结束后销毁对象
// 当返回到主线程的消息循环时,在主线程event queue中的事件被使用notify()方法进行分发
// notify()将事件分发到接收者: receiver->event(event), 即WorkerThread::event(event),最终调用到QObject::event(...)
// first event type = 43 (QEvent::MetaCall), event type = 52 (QEvent::DeferredDelete)
// QEvent::MetaCall(An asynchronous method invocation via QMetaObject::invokeMethod()), 主要用于signal-slot机制
bool WorkerThread::event(QEvent *e) {    
    if (e->type() == QEvent::DeferredDelete) {
        qDebug() << "no event loop, thread id: " << QThread::currentThreadId() << ", DeferredDelete";
    }
    bool result = QThread::event(e);

    qDebug() << "no event loop, thread id: " << QThread::currentThreadId() << ", after QThread::event(...) with type = " << e->type();

    return result; //QThread::event(e);
}

// 主线程执行slotThreadFinished
// 调用deleteLater后将消息接收者WorkerThread以及QDeferredDeleteEvent事件加入到主线程的event queue
void WorkerThread::slotThreadFinished() {
    qDebug() << "no event loop, thread id: " << QThread::currentThreadId() << ", thread finished";
    deleteLater();
}

Controller2::Controller2(QObject *parent) : QObject(parent) {

}

void Controller2::doSomething() {
    WorkerThread *thread = new WorkerThread;
    connect(thread, &QThread::finished, thread, &WorkerThread::slotThreadFinished);
    connect(thread, &WorkerThread::resultReady, this, &Controller2::slotHandleResult);
    thread->start();
}

void Controller2::slotHandleResult(const QString &result) {
    qDebug() << "thread id: " << QThread::currentThreadId() << ", " << result;
}

参考:Qt Assistant - QThread Class

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值