2017-06-02 74 views
1

我正在用Qt開發一個應用程序,從而我想用另一個不同線程中執行的函數更新我的GUI。Qt:qt不能將事件發送到不同線程擁有的對象 - 爲什麼

我使用標準C++構造函數std :: function和std :: bind從Qt GUI類註冊了一個回調函數。

在試圖從其他類執行GUI回調函數時,我的程序崩潰,「qt無法將事件發送給其他線程擁有的對象」。

我的問題是,這裏發生了什麼。爲什麼不能像這樣在兩個線程之間進行通信。是否有可能以某種方式解決這個問題,或者Qt是否不允許其他不相關的函數以這種方式更新GUI?

有關信息,我正在使用Windows上的portaudio庫。它在不同的線程中執行回調。當我收到音頻時,我嘗試更新我的GUI。

預先感謝您

+0

[可能](https://stackoverflow.com/questions/638251/how-to-emit-cross-thread-signal-in-qt)[dupes](https://stackoverflow.com/questions/2086142/qt-signaling-across-threads-one-is-gui-thread),但它們相當老。 [這一個](https://stackoverflow.com/questions/40382820/how-to-leverage-qt-to-make-a-qobject-method-thread-safe)不太適合這個問題,但現代和應該回答這個問題。 – nwp

+0

您可以嘗試提出有關Java Swing的相同問題。 Java的發明者首先創建了一個名爲AWT的多線程窗口工具包,但是它的工作原理是一個比他們預期的更難的問題。最終,他們放棄了AWT,並創建了一個名爲Swing的新的單線程工具包。他們製作Swing單線程的原因可能適用於任何語言的任何窗口工具包。我不記得我在哪裏閱讀過這篇文章,但您可能可以使用Google找到它。 –

+0

謝謝。我認爲對我來說最簡潔的方式可能是在按下按鈕或其他東西時啓動在我的GUI上運行的QThread。 QThread然後將輪詢我的其他類的標誌並相應地更新GUI。我通常不喜歡投票,但你認爲這是我最好的(或唯一的)選項嗎? – Engineer999

回答

2

您可能被「發送事件」短語所拋棄。在Qt中,這個短語具有嚴格的技術含義。即:

  • 發送事件表示使用QCoreApplication::sendEvent,然後立即在接收器上調用QObject::event發送和接收線程不同時發送事件是錯誤的

  • to post事件表示使用QCoreApplication::postEvent,它將事件發送到接收對象線程的事件隊列。接收器上的QObject::event稍後由接收器線程的事件循環調用。

當對象居住在不同的線程,你不許發送事件,只他們。這指出了您的問題的根本原因/

您在QWidget或派生類上訪問的任何方法必須在其thread()(即主線程)上訪問。 QWidget裏面的所有內容都可以隨意使用sendEvent作爲發送線程和接收對象的線程按合同相同。通過從錯誤的線程調用QWidget方法,您通過間接使用sendEvent來中斷該合同,從而失敗。

只有您自己實施並且線程安全的方法可以從其他線程調用 - 並且它們不能使用sendEvent

相關問題