QThread訊號深入挖掘

2021-06-20 19:04:25 字數 4017 閱讀 9650

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中說的清楚:

原文如下(這段話我們稱為定理一吧):

這麼短的文字一眼就看完了,可是,這是什麼意思呢?又能說明什麼問題呢?看段簡單**:

class

thread: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 

thread thread: 0x1de0

from thread slot_main: 0x1de0

這可以工作,但這是 bradley t. hughes 強烈批判的用法。推薦的方法後面會給出。

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: 0x15c0 

thread 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: 0x1a5c 

from 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程式設計的基礎。它使得程式編寫者不需要了解物件之間的任何關係來幫定物件。我們已...