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
本文原出處是乙個可愛的妹子寫的:
在Vue中使用插槽(slot)
什麼是插槽 顧名思義,乙個蘿蔔乙個坑。子元件建立的標籤插入的內容不會在瀏覽器顯示。這時需要用到vue新的語法slot。vue為什麼要用插槽 元件標籤是元件定義好的內容,當我們想在元件標籤內放一些東西的時候。是不具有作用的。他不會顯示。hello 瀏覽器中不會顯示hello。dom結構中也沒有div ...
如何在Vue中使用slot定義元件
一 前言 在react中,可以將元件理解為上下層級,使用children在子層級作為巢狀渲染,但是vue提供方案為slot,並且相對於react,還提供插槽的擴充套件功能,主要分為三種,匿名插槽 類似與children 具名插槽,作用域插槽 可以提供資料繫結 二 匿名插槽 類似與react的chil...
QThread的使用總結
bradley t.hughes 認為 qthread 應該被看做是作業系統執行緒的介面或控制點,而不應該包含需要在新執行緒中執行的 需要執行的 應該放到乙個qobject的子類中,然後將該子類的物件movetothread到新執行緒中。public slots void emitsig signa...