2013-04-07 67 views
2

我在不使用Qt的不同DLL項目中封裝了使用Qt的libcommuni。據我所知,我需要運行Qt消息泵(通過QCoreApplication)以確保網絡,信號等正常工作。但是,我遇到了一些解決如何做到這一點的問題。元帥調用Qt主線程

基本上,我想旋轉一個DLL中的線程,該線程調用QCoreApplication::exec()並抽取所有Qt事件。然後我想將外部調用編組到Qt主線程的不同線程中,這樣我就可以安全地使用libcommuni。

它看起來像推薦的方法是使用信號和插槽,但我一直無法得到這個工作。我在通過DLL調用的QObject類上創建一個信號,並將它連接到運行Qt消息泵的QThread上的一個插槽。但是,如果在連接信號和插槽時指定Qt::QueuedConnection,則發出信號時不會傳送消息。如果我完全省略了Qt::QueuedConnection,那麼該槽將在調用線程上立即調用,而不是在Qt主線程中調用。

我也試過在DLL線程上明確調用QCoreApplication::postEvent()來發送事件給Qt主線程,但event(QEvent)永遠不會在目標QThread中調用。

任何想法,我在做什麼錯在這裏?我猜測我不太瞭解Qt的線程模型。

回答

1

當使用QObject::connect不指定連接類型 - 它使用Qt::AutoConnection,如果信號和槽是在單個線程中哪個變成Qt::DirectConnection,或成Qt::QueuedConnection,如果它們是在不同的線程。因此,就你而言,我可以說,就目前而言,當你將信號與插槽連接時,它們所屬的對象位於一個線程中。

爲了使Qt::QueuedConnection正常工作,您需要一個線程中的事件循環,其中包含插槽。

有使用的QThread的方式主要有兩種:

  1. 可以派生QThread和重寫QThread::run。在這種情況下,你應該做幾件事:

    • 當創建你的線程對象時,不要指定父;手動刪除此對象。
    • 在你的線程的構造函數調用moveToThread(this)
    • 在你的線程的run方法調用exec後全部初始化,但在全部刪除之前;線程將在撥打QThread::quit後立即離開exec
  2. 可以派生QObject,創建QThread對象,並調用QThread::start之前調用你的對象(其中,順便說一下,應該沒有指定父創建)上QThread::moveToThread

在你的情況,我會建議使用第二種方法。

這是關於線程,但我不太確定,您的問題沒有與QCoreApplication::exec連接。