在QThread中使用slots

2021-07-06 00:03:40 字數 4022 閱讀 7483

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

本文原出處是乙個可愛的妹子寫的:

在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...