簡體   English   中英

從工作線程發出Qt :: signal默認情況下會在主線程上更新UI?

[英]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++ signalQML slot

QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));

所有這些都很好。 沒有崩潰,沒有鎖定,什么也沒有。

根據我的理解,由於工作線程的函數正在觸發回調,因此在收到回調時,執行控制位於工作線程上。 因此,當執行emit SignalUpdateData(someValue) ,我們仍在工作線程上。 據我以前在androidjava經驗所知,我們無法從應用程序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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM