[英]Emitting a Qt::signal from worker thread makes the UI update on main thread by default?
我是Qt
新手。 我有一個工作線程,它是一個std::thread
。 輔助線程函數連續循環獲取一些數據。 數據大小經常在QML
UI的Text
元素上更新。 我有一個監聽器回調,只不過是一個std::function
,它是從thread's function
。 它向我發送回調,基於這些回調我更新了QML
上的Text
元素。 我使用signal slot
機制對其進行更新。
以下是QML : Text
元素:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData
與位於QML
側的slotUpdateData
連接。 每次從std::thread
獲得數據事件回調時,我emit SignalUpdateData
來更新UI
上的QML Text element
。
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
以下是我如何將此C++ signal
與QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
所有這些都很好。 沒有崩潰,沒有鎖定,什么也沒有。
根據我的理解,由於工作線程的函數正在觸發回調,因此在收到回調時,執行控制位於工作線程上。 因此,當執行emit SignalUpdateData(someValue)
,我們仍在工作線程上。 據我以前在android
& java
經驗所知,我們無法從應用程序main thread
之外的任何位置更新UI。
那么,這如何運作? 是否emit SignalUpdateData(someValue)
將調用放入main UI thread's event loop
? 盡管我從worker thread
調用它,但Qt
仍在對main thread
進行UI更改嗎? 如果我的方法很好,那么對性能有影響嗎? 這樣做的最佳建議是什么?
我想對此非常確定,而不僅僅是能使它工作起來很幸運。 我是否也應該使用Qt :: Connection_enum以獲得最佳方法?
您正在按原定的方式利用Qt! 而且您偶然遇到了它:這是一個不錯的設計的標志-它“有效”。 為您萬歲,為Qt萬歲:)
之所以起作用,是因為Qt是專門為使其工作而設計的,並且您正在使用默認的自動連接,在這種情況下,它的存在理由將為您提供幫助。 因此,您恰好做對了所有事情:什么都不要改變!
當您發出信號時,Qt將獲取相關的源對象和目標對象互斥量,並將接收對象的thread()
與QThread::currentThread()
。 如果它們相同,則立即調用slot / functor:它發生在信號主體中,因此在信號返回之前調用slot。 這是安全的,因為可以從目標對象的thread()
使用目標對象。
如果target->thread() != QThread::currentThread()
,則QMetaCallEvent
排隊到目標對象。 該事件包含(等效於)插槽方法指針和該插槽傳遞的任何參數的副本。 QObject::event
實現處理事件並執行調用。 目標對象線程的事件循環在調用堆棧上,因為它的工作是將排隊的事件傳遞給對象。
簡而言之,以上是Qt::AutoConnection
的含義。 如果您使用的是Qt::QueuedConnection
,則無論線程是什么, Qt::QueuedConnection
情況都適用。 如果您使用的是Qt::DirectConnection
,則第一種情況無論如何都適用。
我的猜測是,在與Qt有關的SO問題中,非自動連接類型的使用中> 95%是不必要的,並且是由於缺乏理解和訴諸於魔咒。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.