qthread訊號深入挖掘
lin_guoqian
qthread 似乎是很難的乙個東西,特別是訊號和槽,有非常多的人(儘管使用者本人往往不知道)在用不恰當(甚至錯誤)的方式在使用 qthread,隨便用google一搜,就能搜出大量結果出來。無怪乎qt的開發人員 bradley t. hughes 聲嘶力竭地喊you are-doing-it-wrong
和眾多使用者一樣,初次看到這個時,感到 bradley t. hughes有 些莫名奇妙,小題大作。儘管不舒服,當時還是整理過一篇部落格qthread 的使用方法
時間過去3個月,儘管依然沒怎麼用thread;但今天csdn論壇中有人問到這個問題,想想還是盡我所能整理一下吧。提公升自己,方便他人,何樂而不為呢?
qthread東西還是比較多的,而且我對底層物件了解有限,僅就一點進行展開(或許是大家最關心的一點):qthread中的slots在那個執行緒中執行?
run 函式是做什麼用的?manual中說的清楚:
原文如下(這段話我們稱為定理一吧):
這麼短的文字一眼就看完了,可是,這是什麼意思呢?又能說明什麼問題呢?看段簡單**:
classthread:public
qthread
public
slots:
void
slot()
signals:
void
sig();
protected:
void
run()
};int
main(int
argc, char** argv)
對照前面的定理,run函式中的**時確定無疑要在次執行緒中執行的,那麼其他的呢?比如 slot 是在次執行緒還是主線程中執行?
你想說主線程,但又心有不甘,對麼?
涉及訊號槽,我們就躲不過 connect 函式,只是這個函式大家太熟悉。我不好意思再用一堆廢話來描述它,但不說又不行,那麼折中一下,只看它的最後乙個引數吧(為了簡單起見,只看它最常用的3個值)
下面的列表,我們暫稱為定理二:
直接連線(direct connection)
佇列連線(queued connection)
同前面一樣,這些文字大家都能看懂。但含義呢?
不妨繼續拿前面的例子來看,slot 函式是在主線程還是次執行緒中執行呢?
自動連線告訴我們:二者不在同一執行緒時,等同於佇列連線。即 slot 在主線程執行
太繞了?不是麼(要徹底理解這幾句話,你可能需要看qt meta-object系統和qt event系統)
如果上兩節看不懂,就記住下面的話吧(自己總結的,用詞上估計會不太準確)。
但上兩種解決方法都不好,因為qthread不是這麼用的(bradley t. hughes)
好了,不在新增更多文字了,看**,估計咱們都會輕鬆點
這是 qt manual 和 例子中普遍採用的方法。
但由於manual沒說槽函式是在主線程執行的,所以不少人都認為它應該是在次執行緒執行了。
#include / #
include /
qobject> #
include /
qthread>
#include /
qdebug>
class
dummy:public
qobject
public
slots:
void
emitsig()
signals:
void
sig();
}; class
thread:public
qthread
public
slots:
void
slot_main()
protected
: void
run()
};#include "main.moc"
intmain(int
argc, char *argv)
然後看到結果(具體值每次都變,但結論不變)
main thread: 0x1a40 from thread slot_main: 0x1a40 thread thread: 0x1a48看到了吧,槽函式的執行緒和主線程是一樣的!
如果你看過qt自帶的例子,你會發現 qthread 中 slot 和 run 函式共同操作的物件,都會用qmutex鎖住。為什麼?
因為slot和run處於不同執行緒,需要執行緒間的同步!
如果想讓槽函式slot在次執行緒執行(比如它執行耗時的操作,會讓主線程死掉),怎麼解決呢?
main thread: 0x13c0這可以工作,但這是 bradley t. hughes 強烈批判的用法。推薦的方法後面會給出。thread thread: 0x1de0
from thread slot_main: 0x1de0
qthread 定義槽函式,過載run函式
#include / #
include /
qobject>
#include /
qthread>
#include /
qdebug>
class
dummy:public
qobject
public
slots:
void
emitsig()
signals:
void
sig();
};class
thread:public
qthread
public
slots:
void
slot_thread()
signals:
void
sig();
protected:
void
run()};#
include "main.moc"
intmain(int
argc, char *argv)
想看結果麼?
main thread: 0x15c0thread thread: 0x1750
from thread slot_thread: 0x15c0
如何解決呢?
千呼萬喚始出來。
其實,這個方法太簡單,太好用了。定義乙個普通的qobject派生類,然後將其物件move到qthread中。使用訊號和槽時根本不用考慮多執行緒的存在。也不用使用qmutex來進行同步,qt的事件迴圈會自己自動處理好這個。
#include / #
include /
qobject> #
include /
qthread> #
include /
qdebug>
class
dummy:public
qobject
public
slots:
void
emitsig()
signals:
void
sig();
};class
object:public
qobject
public
slots:
void
slot()
};#include "main.moc"
intmain(int
argc, char *argv)
結果:恩,slot確實不在主線程中執行(這麼簡單不值得歡呼麼?)
main thread: 0x1a5cfrom thread slot: 0x186c
深入理解 QThread
派生 qthread 並重寫 run 函式。include include class thread public qthread int main int argc,char argv 輸出結果大致如下 from main thread 0x1d5c from worker thread 0x1b...
vue深入挖掘日記
在用了vue快一年後,已經有了專案經驗的基礎上,再回頭看vue官網,會發現很多以前遺漏的或者用不到但實際上必須要了解的知識。重新學習!深入了解vue原理!q0 vue元件通訊props須知 props不建議使用陣列,props 物件 props props的值一般無法修改,但如果是基本資料型別的話,...
深入訊號與插槽
深入訊號與插槽 signals and slots in depth prentice hall ptr.c gui programming with qt 4.jun.2006 選自chapter 2 訊號與插槽是 qt程式設計的基礎。它使得程式編寫者不需要了解物件之間的任何關係來幫定物件。我們已...