总结使用QObject实现线程

补充一下为什么需要使用继承QObject来实现线程:

原因就是使用继承QThread的类只有run函数是属于新线程的,而其他非run函数依旧属于旧的线程。如果QThread是在ui所在的线程里生成,那么QThread的其他非run函数都是和ui线程一样的,所以,QThread的继承类的其他函数尽量别要有太耗时的操作,要确保所有耗时的操作都在run函数里。在UI线程下调用QThread的非run函数(其实也不应该直接调用run函数,而应该使用start函数),和执行普通函数无区别,这时,如果这个函数要对QThread的某个变量进行变更,而这个变量在run函数里也会被用到,这时就需要注意加锁的问题,因为可能这个变量前几毫秒刚刚在run中调用,再调用时已经被另外的线程修改了。

话不多说,直接上代码,里边有我的注释:

//main.cpp

#include <QtCore/QCoreApplication>
#include "Controller.h"

/*
使用QObject创建线程总结:
1、随便写一个类继承自QObject
2、定义一个工作函数,将耗时的过程写在里边
3、写一个线程管理类,该类至少包含一个QThread和一个你自定义的工作类成员变量
4、在管理类的构造函数中将自定义工作类的对象使用moveToThread()函数移动到QThread对象中,此时该对象的所有东西都是线程对象的了
5、没必要重写run函数,只要在控制类中自定义一个工作信号,并将该工作信号于你自定义的工作函数连接起来,每当发出工作信号,工作函数就开始执行
6、必须在发出工作信号之前执行线程对象的start()函数,否则工作函数无法执行
7、当工作函数中存在while循环时,如果你想手动终止线程中的while循环,那么一定不能使用属于线程的槽函数,因为此时消息队列被线程中的while‘饿死’了。
*/

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Controller control;
    control.Start();

    return a.exec();
}
//cyx_Worker.h

#pragma once
#include <QObject>
#include <QMutex>

class cyx_Worker :public QObject {
    Q_OBJECT
public:
    cyx_Worker(QObject* parent = 0);
    ~cyx_Worker();
    void Stop();

public slots:
    virtual void slot_doWork();

private:
    bool m_bstop;
    QMutex m_mutex;
};
//cyx_Worker.cpp

#include "cyx_Worker.h"
#include <QDateTime>
#include <QMutexLocker>
#include <iostream>
using namespace std;

cyx_Worker::cyx_Worker(QObject* parent /* = 0 */) :QObject(parent) {
    m_bstop = false;
}

cyx_Worker::~cyx_Worker(){}

void cyx_Worker::slot_doWork() {
    qint64 currenttime = QDateTime::currentMSecsSinceEpoch();
    int count = 0;
    {
        QMutexLocker locker(&m_mutex);
        m_bstop = false;
    }
    while (!m_bstop) {
        if (QDateTime::currentMSecsSinceEpoch() - currenttime >= 2000) {
            currenttime = QDateTime::currentMSecsSinceEpoch();
            cout << count << endl;
            count++;
        }
    }
}

void cyx_Worker::Stop() {
    cout << "stop!" << endl;
    QMutexLocker locker(&m_mutex);
    m_bstop = true;
}
//Controller.h

#pragma once
#include <QThread>
#include <QTimer>
#include "cyx_Worker.h"

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

signals:
    void sig_stop();
    void sig_doWork();

public slots:
    void slot_stop();

private:
    QThread m_workthread;
    QTimer* timer;
    cyx_Worker* m_worker;
};
//Controller.cpp

#include "Controller.h"
#include <iostream>
using namespace std;

Controller::Controller(QObject* parent /* = 0 */) :QObject(parent) {
    m_worker = new cyx_Worker;
    timer = new QTimer;
    m_worker->moveToThread(&m_workthread);
    connect(timer, SIGNAL(timeout()), this, SIGNAL(sig_stop()));
    connect(&m_workthread, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
    connect(this, SIGNAL(sig_doWork()), m_worker, SLOT(slot_doWork()));
    connect(this, SIGNAL(sig_stop()), this, SLOT(slot_stop()));
}

Controller::~Controller() {
    m_workthread.quit();
    m_workthread.wait();        //m_workthread并没有new出来,所以使用wait等待线程执行结束,如果使用new,则需绑定deleteLater让线程自杀
}

void Controller::Start() {
    timer->setSingleShot(true);
    timer->start(10000);
    m_workthread.start();
    emit sig_doWork();
}

void Controller::slot_stop() {
    m_worker->Stop();
}
温润如玉,坚毅如铁。
原文地址:https://www.cnblogs.com/heisen/p/10561335.html