Qt-多线程-最好使用官方推荐的方式

主线程(GUI线程)

 

可重入和线程安全

If a function is not marked as thread-safe or reentrant, it should not be used from different threads. If a class is not marked as thread-safe or reentrant then a specific instance of that class should not be accessed from different threads.

// 可重入
// 比如一个类,在每个线程中创建一个实例进行使用

// 线程安全
// 比如一个类,在每个线程中使用同一个实例

// 没有标明可重入和线程安全
// 比如一个类,就在一个线程中使用,不要多个线程创建多个实例

 

线程,线程对象,对象

#include <QCoreApplication>
#include <QThread>
#include <QDebug>

// 每个对象都有一个归属的线程,依附在固定的线程上运行


class TestThread : public QThread
{
private:
    QObject obj; // 在主线程

protected:
    void run()
    {
        qDebug() << "in TestThread run " << QThread::currentThread();
        QObject obj_t; // run函数内,就是进入了线程内部
        // obj_t 依附于子线程

        qDebug() << "not in run " << obj.thread();
        qDebug() << "in run " << obj_t.thread();
        qDebug() << "in run this " << this->thread();
        // this代表线程对象的指针,线程对象在主线程上构建,所以依附于主线程
        // exec(); // 如果要开启子线程事件循环
    }
};

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

    TestThread tt; // 线程对象,用于管理线程,并不是线程
    tt.start();    // 开启线程

    qDebug() << "in main " << tt.thread(); // 线程对象所在的线程是主线程

    return a.exec(); // 主线程事件循环
}

/*
in TestThread run QThread(0x2802d4f8e0)
in main QThread(0x1becf00ae20)
not in run QThread(0x1becf00ae20)
in run QThread(0x2802d4f8e0)
in run this QThread(0x1becf00ae20)
*/

 

 


多线程较好的实践

参考Qt帮助文档

 

 **stackoverflow** 

The way the QThread lifecycle works is like this: 1. You call QThread::start(). 2. At this point, isRunning() should start returning true. 3. The thread internals start. They emit the started() signal. 4. The thread internals call run(). 5. Unless you override this in a subclass, run() calls exec(). 6. exec() enters an event loop and stays there until quit() or exit() is called. 7. exec() and run() return to the internals. 8. At this point, isFinished() should start returning true and isRunning() false. 9. The internals emit the finished() signal. 10. The internals do some final cleanups. 11. The thread terminates for real.

 

 

class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const QString &parameter)
    {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }

signals:
    // 工作完成后,发射信号
    // 并且把处理的结果作为参数传出
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;

public:
    Controller()
    {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread); // 改变work的依附线程

        // workerThread 结束后,worker被Controller所在线程接管
        // workerThread发射finished信号是在workerThread所在线程,而不是在run中
        // workerThread和worker在同一线程
        // 连接是Qt::DirectConnection
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);

        // Qt::QueuedConnection
        connect(this, &Controller::operate, worker, &Worker::doWork);

        // Qt::QueuedConnection
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
    }
    ~Controller()
    {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

 

posted @ 2020-08-22 09:13  duohappy  阅读(758)  评论(0编辑  收藏  举报