對不起,這篇文章的長度。但我堅持了兩天吧....QThread無法啓動
我正在通過ActiveX與硬件設備通信的Qt 4.6 Windows應用程序。
當我發送一個命令時,設備會做一些事情,當它完成時(可能需要一分鐘)它會發出一個信號。我需要等待這個信號,以確定是否一切正常(或不),並採取一些行動。
當用戶單擊按鈕時,將向設備發送命令。顯然,我不希望HMI凍結。
我確信我必須使用線程。因此,我確定了三個線程:
- 對應於HMI
- 硬件控制器(被髮送的命令後,其鎖定和等待的信號)
- 硬件通知監聽器連續地從得到的信號的主線程硬件和解鎖線程2
下面是類圖:
和序列圖來展示我所看到的東西:
說明:
當用戶啓動我的應用程序,創建HMI。 HMI的構造函數調用Worker的構造函數。它構造硬件QAxObject。然後它構造HardwareListener給出的參考:QAxObject,QMutex和QWaitCondition。然後,Worker的構造函數將HardwareListener對象移動到另一個線程並啓動它。最後,HMI的構造函數啓動Worker的線程。
然後,當用戶點擊一個按鈕時,HMI發送一個信號給工人。 Worker向硬件發送命令(該命令可能會在幾秒鐘內阻塞該線程,這就是爲什麼我需要另一個線程中的HardwareListener不會錯過信號的原因)。然後工人等待QWaitCondition(鎖定QMutex後)。
之後,硬件設備發送一個信號給HardwareListener,喚醒QWaitCondition。因此,Worker線程停止等待並完成其操作。最後,工作人員通知HMI。
問題:
不創建工人和HardwareListener線程/啓動。一切都在主線程完成,顯然,它不起作用。我不交換線程(所以沒有必要qRegisterMetaType()
)之間的任何特殊對象
問:
是我設計的可以接受嗎?可能還有其他方法可以做,但在我看來這是最直接的(考慮到複雜性)。
編輯:
我已經改變了我的代碼刪除QThread
繼承。我使用moveToThread()
方法。
現在線程正常工作。但是我有一個ActiveX錯誤:QAxBase: Error calling IDispatch member NewProject: Unknown error
。
看來與硬件的接口被打破了......任何想法?
Here is something interesting:
You cannot move a QAxObject to another thread once it has been created.
SOLUTION:
可以看到一些代碼,也不需要移動到線程。有一些關於不從QThread繼承的帖子。 – paulm 2013-04-09 15:07:54
你必須提供一些代碼..我假設你使用QThread。用QThread實現工作者和聽衆之間的溝通是什麼?你把他們移到新線程嗎?如果你繼承了QThread - 那就停止這樣做。用工人的例子閱讀文檔。 – JustAnotherCurious 2013-04-09 15:16:22
你想看哪部分代碼?我已經試過不從QThread繼承,只是調用'moveToThread()'。它適用於工作人員,但不適用於HardwareListener。 你能解釋爲什麼不需要線程嗎? – Maxbester 2013-04-09 15:17:05