QThread多線程編程經典案例分析(三種方法,解釋了為什么使用moveToThread的根本原因,即為了避免調用QThread::exec() )


傳統的圖形界面應用程序都只有一個線程執行,並且一次執行一個操作。如果用戶調用一個比較耗時的操作,就會凍結界面響應。

一個解決方法是按照事件處理的思路:

調用 Void QApplication::processEvents() 或 void QApplication::processEvents ( int maxtime ) 來強迫事件循環進行,但是這種做法是有潛在風險的。按照QCoreApplication:processEvents()可能會引起遞歸,導致棧溢出崩潰的說法,當主線程在某個槽函數里正在執行processEvents時, 剛好有一個能響應此槽函數的信號發送過(肯定是其他線程發的信號), 這時就可能會發生可怕的遞歸, 導致棧溢出崩潰。 原因是processEvents在處理自己槽函數的事件時,又會調用到processEvents,進入到無盡的遞歸中。

另外一個解決方法是:采用多線程。、

QT QThread多線程編程的方法一直有個爭議,就是Bradley T. Hughes:You’re doing it wrong 歸納為3中方法優劣問題:

方法(1): 
1. 不使用事件循環。這是官方的 Manual 、example 以及相關書籍中都介紹的一種的方法。 
a. 子類化 QThread 
b. 重載 run 函數,run函數內有一個 while 或 for 的死循環 
c. 設置一個標記為來控制死循環的退出。

這里的run函數自己執行了一個循環,不需要事件循環機制了。

 

方法(2):

這種方法也是Bradley T. Hughes極力批判的 a. 子類化 QThread, b. 重載 run 使其調用 QThread::exec() c. 並為該類定義信號和槽,這樣一來,由於槽函數並不會在新開的 thread 運行,很多人為了解決這個問題在構造函數中調用 moveToThread(this); 
而爭論和不解正是這樣的一條語句造成的。 
Bradley T. Hughes 給出說明是: QThread 應該被看做是操作系統線程的接口或控制點,而不應該包含需要在新線程中運行的代碼。需要運行的代碼應該放到一個QObject的子類中,然后將該子類的對象moveToThread到新線程中。

方法(3): 
在Qt4.3(包括)之前,run 是虛函數,必須子類化QThread來實現run函數。而從Qt4.4開始,qthreads-no-longer-abstract ,run 默認調用 QThread::exec() 。這樣一來不需要子類化 QThread 了,只需要子類化一個 QObject 就夠了,這正是被 Bradley T. Hughes推薦的方法。

方法如下

QThread thread; 
Object obj; 
Dummy dummy; 
obj.moveToThread(&thread); 
QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot())); 
thread.start();

所以,方法(1)和方法(3)是正確的QT QThread多線程編程方法,方法(2)用的最多,但只是三人成虎,一種不恰當的用法

http://blog.csdn.net/bladeandmaster88/article/details/51802491

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM