Qt::帶返回值的信號發射方式


一般來說,我們發出信號使用emit這個關鍵字來操作,但是會發現,emit並不算一個調用,所以它沒有返回值。那么如果我們發出這個信號想獲取一個返回值怎么辦呢?

兩個辦法:1.通過出參形式返回,引用或者指針的方式帶回;比如emit sig(int& i)或者emit sig(void* pointer),但是這個方法有一個弊端,稍后介紹第二種方式會提醒。

2.通過qt自帶的invoke機制調用:參考文檔對QMetaObject::invokeMethod的說明:Invokes the member (a signal or a slot name) on the object obj.也就是說回調是可以回調信號或者槽的。一般來說,我們使用invokeMethod是在子線程需要調度UI操作的時候(已經有很多文章詳細說明了使用方式,不再贅述),因為UI操作只能在主線程中使用(否則會出現未定義錯誤),通過這種回調方式,讓要操作的事件回到主線程時間片的時候再來執行。大部分情況下,我們把UI操作封裝在一個槽里,用回調方式來調度。同樣信號也可以用這種方式,但是有幾點需要注意的是,1.調用回調的連接方式:如果信號和連接槽在一個線程內,那么必須用Qt::DirectConnection或者Qt::AutoConnection,這樣的話,保證信號回調后,線程會等待信號連接槽執行完畢,才可能取到我們需要的返回值;如果使用了Qt::QueuedConnection,那么信號只是負責把事件交給事件隊列,然后馬上做出返回,這樣,是否有返回值就無法確定了(這也就是第一個方法的弊端,因為信號發射是根據信號和槽各自的線程情況來選擇的連接方式).如果信號和槽在兩個線程中,那么首先肯定不能使用Qt::DirectConnection,除非你很清楚連接槽的動作是否保證了線程安全。但根據第一條的說明,也不能使用Qt::QueuedConnection。不過還好qt提供了一個額外的連接方式就是Qt::BlockingQueuedConnection,這個連接方式會阻塞住發射信號的線程一直等到隊列連接槽返回后,才會恢復阻塞,這樣就可以保證我們能拿到真正的返回值。(但是使用這種方式需要你清楚的知道,發射線程是否允許阻塞和連接槽是否對這個阻塞線程有什么特別的操作,一般來說,如果這個線程並不是由你自己控制的話,不要隨便嘗試去阻塞別人的線程,因為你並不清楚別人線程的執行邏輯)

調用方式大致代碼如下bool bReturn; QMetaObject::invokeMethod(&object, "sig", Qt::DirectConnection/*Qt::QueuedConnection*/, Q_RETURN_ARG(bool, bReturn), Q_ARG(int, i));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM