學習QT多線程編程以前,有必要先熟悉事件循環的概念。先看一個單線程界面程序的主函數代碼:html
int main(int argc, char* argv[]) { QApplication app(argc, argv); // 構造主窗口對象並顯示 MainWindow w; w.show(); // 進入事件循環 return app.exec(); }
在程序初始化完成後,主線程進入main()函數開始執行應用代碼。通常地,咱們在主線程上構建界面對象,而後進入事件循環以處理控件繪製、用戶輸入、系統輸出等消息。這就是咱們一般說的事件驅動模型。編程
主線程承擔着用戶交互的重任,當在主線程上運行費時的代碼時,就會影響用戶的正常操做。因此咱們常把一些費時費力的計算工做移出主線程,開闢新的線程來運行之。安全
QThread是QT中用於線程管理的類,調用一個QThread對象的start()方法時,會建立一個新的線程並執行它的run()方法。默認地,run()會調用exec()方法進入本身的消息循環中。以下圖所示:多線程
上圖中有主線程、工做線程都是執行事件循環,而且注意到主線程內部含有thr、w、objs這些QObject對象(這些對象都是在主線程上建立的)。主線程的事件循環負責檢測這些對象是否有消息要處理,有的話則調用對象的slot方法。可使用QObject::moveToThread方法將某個對象移到其餘線程中,譬如:併發
class Worker : public QObject { Q_OBJECT … } void someFunc() { QThread thr = new QThread; Worker worker = new Worker; worker->moveToThread(thr); thr->start();
… }
若是在主線程上調用someFunc(),則workerThread和worker在建立後都是關聯在主線程上,當調用worker->moveToThread()後,worker對象關聯到了新的線程中,如圖所示:app
假定咱們在MainWindow上聲明瞭一個worksSignal()消息,在Worker對象上聲明和定義了handleWorks()的槽,將worksSignal和handleWorks鏈接起來的方式有:函數
1. Qt::AutoConnection - (默認)若是消息對象和槽對象關聯在同一線程下,則使用Qt::DirectConnection方式;不然的話,像MainWindow和Worker兩個關聯在不一樣線程的對象,將採用Qt::QueuedConnection的方式。post
2. QT::DirectConnection - 發送消息的時候將直接調用槽對象的槽方法。注意這裏的槽方法是在發送消息的線程上執行的,若是該槽方法是非線程安全的話會有問題的。學習
3. Qt::QueuedConnection - 發送線程在發送消息後將繼續執行,槽對象關聯的線程在事件循環時會檢測到該消息,並調用相應的槽方法。url
4. Qt::BlockingQueuedConnection - 在主線程發送worksSignal消息後,將阻塞直到在工做線程檢測到該消息並運行worker->handleWorks()後恢復。
5. Qt::UniqueConnection - 能夠和上面4個方式聯並(或操做),提示該鏈接是獨一的。提示不能有相同的鏈接(消息對象和槽對象,消息和槽都相同)出現。
這裏特別提醒讀者,通常地咱們不建議將QThread對象moveToThread到它運行的線程上。緣由是QThread是設計成一個管理線程的類,咱們不該該在工做線程上管理工做線程,對吧。關於更多的技術細節,我不想多講了,由於本系列的博文旨在共享經驗技巧,而非翻譯一些文檔。
在項目中,我都是經過繼承QThread類實現後臺進程的,經過重寫run()函數填入線程須要運行的任務。上一篇博文中,我經過在QThread子類上嵌入InThreadObject對象快速實現線程通訊的功能,請回顧QT高級編程技巧(一)-- 編寫高效的signal & slot通訊代碼。還有下面一個技巧實現工做線程上的timer事件處理:
void WorkerThread::run() { QTimer tmr; // 關聯在本線程上的QObject對象 connect(&tmr, &QTimer::timeout, [=](){ doSomething(); }); tmr.start(500); // 500毫秒計時 exec(); // 進入事件循環 }
關於多線線程的編程談論到此,望能起拋磚引玉的效果。在實際的項目,能夠參考下面的文檔設計多線程或併發的應用:
* QtConcurrent: http://doc.qt.io/qt-5/qtconcurrent.html
* Thread Support in Qt: http://doc.qt.io/qt-5/threads.html
本文連接:http://www.cnblogs.com/wenris/p/4450643.html。
做者:wenris,聯繫:<wenris AT yeah.net>
後會有期哦 O(∩_∩)O