標籤:事件 圖形 start dea 正是 重載 經典 arp 問題
傳統的圖形介面應用程式都只有一個線程執行,並且一次執行一個操作。如果使用者調用一個比較耗時的操作,就會凍結介面響應。
一個解決方案是按照事件處理的思路:
調用 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
QThread多線程編程經典案例分析(三種方法,解釋了為什麼使用moveToThread的根本原因,即為了避免調用QThread::exec() )