傳統圖形介面應用程式都只有乙個執行緒執行,並且一次執行乙個操作。如果使用者呼叫乙個比較耗時的操作,就會凍結介面響應。乙個解決方法是按照事件處理的思路:呼叫
或來強迫事件迴圈進行,但是這種做法是有潛在風險的。 按照
可能會引起遞迴,導致棧溢位崩潰的說法,當主線程在某個槽函式裡正在執行
processevents
時,剛好有乙個能響應此槽函式的訊號傳送過(肯定是其他執行緒發的訊號),這時就可能會發生可怕的遞迴,導致棧溢位崩潰。原因是
processevents
在處理自己槽函式的事件時,又會呼叫到
processevents
,進入到無盡的遞迴中。
另外乙個解決方法是:採用多執行緒。
qt qthread
多執行緒程式設計的方法一直有個爭議,就是
bradley t. hughes
:you
』re doing it wrong
歸納為3
中方法優劣問題:
不使用事件迴圈。這是官方的
manual
、example
以及相關書籍中都介紹的一種的方法。
子類化qthread;過載
run
函式,run
函式內有乙個
while
或for
的死迴圈;
設定乙個標記為來控制死迴圈的退出。
這種方法也是
bradley t. hughes
極力批判的。
子類化qthread;過載
run
使其呼叫
qthread::exec()
;並為該類定義訊號和槽,這樣一來,由於槽函式並不會在新開的
thread
執行,很多人為了解決這個問題在建構函式中呼叫
movetothread(this);
而爭論和不解正是這樣的一條語句造成的。
bradley t. hughes
給出說明是:
qthread
應該被看做是作業系統執行緒的介面或控制點,而不應該包含需要在新執行緒中執行的**。需要執行的**應該放到乙個
qobject
的子類中,然後將該子類的物件
movetothread
到新執行緒中。
在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)子類化
qthread
的run()
函式裡,在
run()
函式裡執行耗時的操作。因為
run()
函式是子執行緒的入口函式,一定不和主線程在同乙個執行緒。就是方法
1介紹的。如果在
qthread
子類裡的
slot
裡執行耗時操作,因為
slot
是在主線程中執行的,所以行不通。 (
2)利用方法(
3),子類化
qobject ,
如object
。在object
的slot
裡執行耗時操作。但是
slot
仍在主線程裡執行,怎麼辦?
qthread *thread
;object.movetothread(thread);
這樣,這個
qobject
的slot
都會在子執行緒裡執行,達到了和主線程區分開的目的啦。
所以,方法(
1)和方法(
3)是正確的
qt qthread
多執行緒程式設計方法,方法(
2)用的最多,但只是三人成虎,一種不恰當的用法。下面給出方法(
1)和方法(
3)的**片段,各種思路請慢慢斟酌。
主線程開兩個子執行緒,子執行緒a列印
a,子執行緒b列印
b,通過乙個
dialog
控制。
(1)thread.h:
#ifndef thread_h
#define thread_h
#include
class thread : public qthread ;
#endif
(2)threaddialog.h:
#ifndef threaddialog_h
#define threaddialog_h
#include
#include "thread.h"
class qpushbutton;
class threaddialog : public qdialog ;
#endif
(3)thread.cpp
#include
#include
#include "thread.h"
thread::thread()
void thread::setmessage(const qstring &message)
void thread::run()
void thread::stop()
(4)threaddialog.cpp
#include
#include "threaddialog.h"
threaddialog::threaddialog(qwidget *parent)
: qdialog(parent)
void threaddialog::startorstopthreada()
else }
void threaddialog::startorstopthreadb()
else }
void threaddialog::closeevent(qcloseevent *event)
(5)main()
#include "threaddialog.h"
int main(int argc, char *ar**)
測試結果:
結果:slot
確實不在主線程中執行。
main thread: 0x1a5c
from thread slot: 0x186c
其他
QThread多執行緒程式設計經典案例分析
傳統的圖形介面應用程式都只有乙個執行緒執行,並且一次執行乙個操作。如果使用者呼叫乙個比較耗時的操作,就會凍結介面響應。乙個解決方法是按照事件處理的思路 另外乙個解決方法是 採用多執行緒。qt qthread多執行緒程式設計的方法一直有個爭議,就是bradley t.hughes you re doi...
QThread多執行緒程式設計經典案例分析
傳統的圖形介面應用程式都只有乙個執行緒執行,並且一次執行乙個操作。如果使用者呼叫乙個比較耗時的操作,就會凍結介面響應。乙個解決方法是按照事件處理的思路 另外乙個解決方法是 採用多執行緒。qt qthread多執行緒程式設計的方法一直有個爭議,就是bradley t.hughes you re doi...
Qt多執行緒開發 QThread
件 class mythread public qthread mythread virtual void run cpp檔案 void mythread run 件 class mythread public qthread mythread virtual void run class move...