示例
moveToThread示例
要点
- 使用moveToThread()创建子线程;
- 使用QMutex/QWaitCondition进行线程同步(适用情况:子线程主动挂起,等待主线程唤醒)。
代码
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QMutex>
#include <QWaitCondition>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject* parent = nullptr);
public:
void DoWorker();
void RecoverWork();
signals:
void SignalRecover();
void SignalStart();
private slots:
void OnRecovered();
void OnStarted();
private:
QMutex m_mutex;
QWaitCondition m_waitCondition;
};
#endif // WORKER_H
worker.cpp
#include "worker.h"
#include <QDebug>
#include <QThread>
Worker::Worker(QObject *parent)
: QObject{parent}
{
connect(this, &Worker::SignalStart, this, &Worker::OnStarted);
connect(this, &Worker::SignalRecover, this, &Worker::OnRecovered);
}
void Worker::DoWorker()
{
qDebug() << QThread::currentThreadId() << "in DoWorker";
emit SignalStart();
}
void Worker::RecoverWork()
{
qDebug() << QThread::currentThreadId() << "in RecoverWork";
qDebug() << QThread::currentThreadId() << "m_waitCondition.wakeAll";
m_waitCondition.wakeAll();
}
void Worker::OnRecovered()
{
qDebug() << QThread::currentThreadId() << "in OnRecovered";
}
void Worker::OnStarted()
{
qDebug() << QThread::currentThreadId() << "in OnStarted";
int i = 0;
while (true)
{
m_mutex.lock();
qDebug() << QThread::currentThreadId() << "in OnStarted sleep" << i;
QThread::sleep(1);
++i;
if (i % 5 == 0)
{
qDebug() << QThread::currentThreadId() << "m_waitCondition.wait" << i;
m_waitCondition.wait(&m_mutex);
}
m_mutex.unlock();
}
}
contrllor.h
#ifndef CONTRLLOR_H
#define CONTRLLOR_H
#include <QObject>
class Worker;
class Contrllor : public QObject
{
Q_OBJECT
public:
explicit Contrllor(QObject* parent = nullptr);
~Contrllor();
public:
Q_INVOKABLE void doWork();
Q_INVOKABLE void pauseWork();
Q_INVOKABLE void recoverWork();
Q_INVOKABLE void test();
signals:
private:
QThread* m_workerThread;
Worker* m_worker;
};
#endif // CONTRLLOR_H
contrllor.cpp
#include "contrllor.h"
#include <QDebug>
#include <QThread>
#include "worker.h"
Contrllor::Contrllor(QObject *parent)
: QObject{parent}
{
qDebug() << "in Contrllor";
m_workerThread = new QThread;
m_worker = new Worker;
m_worker->moveToThread(m_workerThread);
m_workerThread->start();
}
Contrllor::~Contrllor()
{
qDebug() << QThread::currentThreadId() << "in ~Contrllor";
m_workerThread->terminate();
if (m_workerThread->wait())
{
delete m_worker;
delete m_workerThread;
}
qDebug() << QThread::currentThreadId() << "out ~Contrllor";
}
void Contrllor::doWork()
{
qDebug() << QThread::currentThreadId() << "in doWork";
m_worker->DoWorker();
}
void Contrllor::pauseWork()
{
qDebug() << QThread::currentThreadId() << "in pauseWork";
// TODO-gy-2023-10-15
}
void Contrllor::recoverWork()
{
qDebug() << QThread::currentThreadId() << "in recoverWork";
m_worker->RecoverWork();
}
void Contrllor::test()
{
qDebug() << QThread::currentThreadId() << "in test";
}
关于QWaitCondition
wakeOne与wakeAll的区别
wakeAll
唤醒所有处于等待状态的线程。线程被唤醒的顺序取决于操作系统的调度策略,无法控制或预测。
wakeOne
在等待条件下唤醒一个线程。被唤醒的线程取决于操作系统的调度策略,无法控制或预测。
注意:如果想唤醒一个特定的线程,通常是使用不同的等待条件,并让不同的线程在不同的条件下等待。
引用
QThread Class | Qt Core 5.15.15
QThreadPool Class | Qt Core 5.15.15
Synchronizing Threads | Qt 5.15