需要注意的是,Qt 的 GUI 相關的實現以及更新只能在主線程中完成。
簡易線程創建並使用
auto tempHandleDicomInfoThread = new QThread();
connect(tempHandleDicomInfoThread, &QThread::started, [=]() {
qDebug() << "tempHandleDicomInfoThread started" << tempHandleDicomInfoThread->currentThreadId();
foo();//do something
tempHandleDicomInfoThread->quit();
});
connect(tempHandleDicomInfoThread, &QThread::finished, [=]() {
qDebug() << "tempHandleDicomInfoThread finished" << tempHandleDicomInfoThread->currentThreadId();
tempHandleDicomInfoThread->deleteLater();
});
tempHandleDicomInfoThread->start();
這裏可以體現出創建一個線程公有的步驟:
- 創建一個 QThread 線程對象
- start 這個線程
- 在運行完成後 quit
- 並在線程發出 finished 信號後 delete 這個線程
繼承 QThread 實現多線程
許多博客中寫明瞭並不推薦該用法而是推薦下面的 moveToThread 實現方法,具體原因還在瞭解中。
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(QObject* parent = nullptr);
signals:
void signal_mThread();//自定義發送的信號
public slots:
void slotMyThread();//自定義槽
protected:
void run() override;
};
#include <mythread.h>
Controller::Controller(QObject *parent) : QObject(parent)
{
myThrd = new MyThread;
connect(myThrd, &MyThread::signal_mThread, this, &Controller::handleResults);
connect(myThrd, &QThread::finished, this, &QObject::deleteLater); //該線程結束時銷燬
connect(this, &Controller::operate, myThrd, &MyThread::myThreadSlot);
myThrd->start();
emit operate();
}
Controller::~Controller()
{
myThrd->quit();
myThrd->wait();
}
這裏我們創建了一個基於 QThread 的類,來實現數據的處理。通過接口 operate() 向其傳入數據,通過 signal_mThread() 傳出處理完成的數據。
moveToThread
//moveToThread
class Worker : public QObject {
Q_OBJECT
public:
Worker();
~Worker();
public slots:
void process(){
qDebug()<<"hello world";
emit finfished();
}
signals:
void finished();
void error(QString err);
private:
// add your variables here
};
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
QThread 的使用應該與常規線程實例非常相似:
- 準備一個對象 QObject 類,其中包含所有所需的功能
- 創建一個新的 QThread 實例,使用 QObject 實例的 moveToThread(QThread*) 將 QObject 推送到該實例上
- 並在 QThread 實例上調用 start()
線程同步
//互斥鎖 QMutex
class Worker : public QObject {
Q_OBJECT
public:
Worker();
~Worker();
void setMutex(QMutex &mutex){mMutex = mutex};
public slots:
void process(){
mMutex->lock();
qDebug()<<"hello world";
emit finfished();
mMutex->unlock();
}
signals:
void finished();
void error(QString err);
private:
QPointer<QMutex> mMutex;
};
void foo(){
QMutex mutex;
QThread* thread = new QThread;
auto worker1 = new worker();
auto worker2 = new worker();
//connect ......
worker1->setMutex(mutex);
worker2->setMutex(mutex);
worker1->start();
worker2->start();
}