Qt 線程的詳細介紹和使用
-
QT::QThread類提供了一種獨立於平臺的方式來管理線程。QThread對象管理程序中的一個控制線程。QThreads開始在run()中執行。默認情況下,run()通過調用exec()啓動事件循環,並在線程內部運行Qt事件循環
-
通過使用QObject::moveToThread()將worker對象移動到線程,可以使用它。線程將在運行函數返回後退出。除非調用exec(),否則線程中不會運行任何事件循環。
- 必須記住,QThread實例位於實例化它的舊線程中,而不是調用run()的新線程中。
- 這意味着QThread隊列中的所有插槽都將在舊線程中執行。
- 因此,希望在新線程中調用插槽的開發人員必須使用worker-object方法;不應該將新插槽直接實現到子類QThread中。
- 在子類化QThread時,請記住,構造函數在舊線程中執行,而run()在新線程中執行。
- 如果從兩個函數訪問成員變量,則從兩個不同的線程訪問該變量。檢查一下這樣做是否安全。
- 當線程啓動()和finished()時,QThread將通過一個信號通知您,或者您可以使用isFinished()和isRunning()來查詢線程的狀態。
- 您可以通過調用exit()或quit()來停止線程。在極端情況下,您可能希望強制終止一個正在執行的線程。然而,這樣做是危險的,也是令人氣餒的。詳細信息請閱讀terminate()和setTerminationEnabled()的文檔。
- 從Qt 4.8開始,通過將finished()信號連接到QObject::deleteLater,就可以釋放位於剛剛結束的線程中的對象
- 使用wait()來阻塞調用的線程,直到另一個線程完成執行(或者直到指定的時間過去)。
- QThread還提供靜態的、平臺無關的睡眠函數:sleep()、msleep()和usleep()分別允許完全秒級、毫秒級和微秒級的分辨率。這些功能在Qt 5.0中公開。
- 注意:一般來說,wait()和sleep()函數應該是不必要的,因爲Qt是一個事件驅動框架。考慮偵聽完成的()信號,而不是wait()。不要使用sleep()函數,考慮使用QTimer。
- 靜態函數currentThreadId()和currentThread()返回當前執行線程的標識符。前者返回線程的平臺特定ID;後者返回一個QThread指針。
- 要選擇線程的名稱(例如,通過Linux上的命令ps -L識別),可以在啓動線程之前調用setObjectName()。如果您不調用setObjectName(),給線程的名稱將是線程對象的運行時類型的類名(例如,在Mandelbrot示例中,“RenderThread”是QThread子類的名稱)。請注意,目前在Windows上的版本中還不能使用這個功能。
一:Qthread成員函數介紹:
QThread(QObject *parent = Q_NULLPTR) |
|
~QThread() |
|
QAbstractEventDispatcher * |
eventDispatcher() const 返回指向線程的事件調度程序對象的指針。如果線程不存在事件調度程序,則此函數返回0。 |
void |
exit(int returnCode = 0) 告訴線程的事件循環使用返回代碼退出。 |
bool |
isFinished() const 該信號是在相關線程完成執行之前發出的。 |
bool |
isInterruptionRequested() const 如果在此線程上運行的任務應該停止,則返回true。requestinterrupt()可以請求中斷。 |
bool |
isRunning() const 如果線程正在運行,返回true;否則返回false。 |
int |
loopLevel() const 返回線程的當前事件循環級別。 |
Priority |
priority() const 返回正在運行的線程的優先級。如果線程不運行,該函數返回InheritPriority。 |
void |
請求中斷線程。該請求是建議性的,由線程上運行的代碼決定是否以及如何響應該請求。此函數不會停止線程上運行的任何事件循環,也不會以任何方式終止它。 |
void |
setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) 將線程的事件調度程序設置爲eventDispatcher。只有在還沒有爲線程安裝事件分派器的情況下,纔有可能做到這一點。也就是說,在使用start()啓動線程之前,或者在主線程中,在實例化QCoreApplication之前。此方法擁有對象的所有權。 |
void |
setPriority(Priority priority) 此函數設置正在運行的線程的優先級。如果線程沒有運行,這個函數什麼也不做,並且立即返回。使用start()啓動具有特定優先級的線程。 |
void |
setStackSize(uint stackSize) 將線程的最大堆棧大小設置爲堆棧大小。如果堆棧大小大於零,則將最大堆棧大小設置爲堆棧大小字節,否則操作系統將自動確定最大堆棧大小。 |
uint |
stackSize() const 返回線程的最大堆棧大小(如果設置爲setStackSize());否則返回0。 |
bool |
wait(unsigned long time = ULONG_MAX) 阻塞線程,直到滿足以下任一條件: 與此QThread對象關聯的線程已經完成執行(即當它從run()返回時)。如果線程已經完成,這個函數將返回true。如果線程還沒有啓動,它還返回true。 |
二:run 方法
- QThreads開始在run()中執行。默認情況下,run()通過調用exec()啓動事件循環,並在線程內部運行Qt事件循環
QThread
{
class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
}
三:QObject::moveToThread() 方法
- 通過使用QObject::moveToThread()將worker對象移動到線程,可以使用它。因此,希望在新線程中調用插槽的開發人員必須使用worker-object方法;不應該將新插槽直接實現到子類QThread中。這種方法;
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
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);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
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 &);
};
總結:
具體的一些例子官方已經給出demo:
參見Qt、QThreadStorage、同步線程、Mandelbrot示例、信號量示例和等待條件示例中的線程支持一些實例:
Thread Support in Qt, QThreadStorage, Synchronizing Threads, Mandelbrot Example, Semaphores Example, and Wait Conditions Example.