[英]C++ Threading Pattern for Qt serial port
我的目的是在不阻塞主線程(GUI)的情況下從串行設備接收消息,並嘗試將與平台相關的邏輯(GUI和串行端口)與業務邏輯(處理消息)分開,以便於移植到其他平台
上下文:我正在使用Qt和QtSerialPort模塊。 消息協議很簡單,0xff用於結束每個消息。
到目前為止,我已經找到了4種解決方案:
方法1:
使用一個線程讀取串行端口並填充緩沖區
使用另一個線程讀取緩沖區,提取有效消息(到另一個緩沖區中?不確定如何工作)
使用另一個線程來解析消息
方法2:
使用一個線程讀取串行端口,並將有效消息提取到緩沖區中
使用另一個線程來解析消息
方法3:
方法4:
方法1,2和3的區別在於,一般工作負載被划分為多個線程,盡管我不知道哪個是最好的。
我當前正在使用方法4,由於產生了大量線程,並且每次我移動或與GUI交互時,串行通信都會停止,方法4效率極低,並且在低端計算機上無法很好地工作。 為每條消息生成一個線程也會使消息的順序不確定,這到目前為止並不是一個主要問題。
是否還有其他方法,每種方法各有利弊(如果有),哪種方法最好? 謝謝!
編輯:在主線程中處理消息的一個問題是與GUI交互(甚至移動窗口)將阻止消息處理功能。 有沒有辦法解決?
我認為使用多線程可以獲得兩個主要優點:
您只需要產生一個線程即可。 只是讓線程從串行端口中讀取數據(通過將QSerialPort的readyRead()信號連接到調用QSerialPort對象上的read()的插槽),然后在任何時候發出信號(帶有QByteArray參數)。想要將一些串行數據發送到GUI。 您的main / GUI線程可以通過QueuedConnection接收數據,而QueuedConnection不會阻塞串行線程或main / GUI線程。
這幾乎就是全部了。 唯一需要擔心的是干凈的關機。 確保與QThread的quit()插槽建立另一個跨線程信號/插槽連接,以便在需要退出時,可以發出該信號,然后在QThread上調用wait()以等待它通過以下方式響應遠。 一旦wait()返回,您就可以安全地刪除QThread對象。
您只需要依靠Qt事件循環就可以完全避免使用其他線程(到目前為止,只有當串行端口實際接收到一條消息時,主線程(還要處理GUI的主線程才被阻塞)。
否則,如果您想在專用線程中完全處理串行端口,那么解決方案是實現一個從QThread
派生的類,然后用類似以下的方法覆蓋run()
函數:
void MyClass::run()
{
QSerialPort port;
// ... serial port initialization here
// Connect signals/slots
connect(&port, SIGNAL(readyRead()), this, SLOT(readData()));
port.open();
// Start a new message loop on this thread
exec();
}
其中readData
是在MyClass
實現的用於處理接收到的數據的函數。 由於port
由新線程擁有(在run()
創建),因此它的事件將由線程本身處理(相對於主線程完全獨立)。
如果您想在某個時候與主線程進行通訊(例如:您在串行上收到了某些內容,這可能會導致GUI發生更改),那么您仍然可以使用Qt的信號/插槽。 只需在MyClass
上實現一個信號,然后在由主線程處理的對象上實現一個插槽即可(例如:您的主窗體):然后只需將MyClass
的信號與您的主窗體上的插槽連接起來就可以完成:signals / slots為Qt中跨線程通信解決方案。
您還可以避免使用任何(其他)線程,並利用Qt 事件循環 。 了解事件 , QioDevice ; 然后Qt會將您的設備文件描述符傳遞到其多路復用循環(例如,傳遞給poll(2) ....); QSocketNotifier可能應該在非套接字文件描述符(如串行設備)上運行(在Posix上)。
詳細信息可能是特定於操作系統的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.