簡體   English   中英

Qt串行端口的C ++線程模式

[英]C++ Threading Pattern for Qt serial port

我的目的是在不阻塞主線程(GUI)的情況下從串行設備接收消息,並嘗試將與平台相關的邏輯(GUI和串行端口)與業務邏輯(處理消息)分開,以便於移植到其他平台

上下文:我正在使用Qt和QtSerialPort模塊。 消息協議很簡單,0xff用於結束每個消息。

到目前為止,我已經找到了4種解決方案:

方法1:

  1. 使用一個線程讀取串行端口並填充緩沖區

  2. 使用另一個線程讀取緩沖區,提取有效消息(到另一個緩沖區中?不確定如何工作)

  3. 使用另一個線程來解析消息

方法2:

  1. 使用一個線程讀取串行端口,並將有效消息提取到緩沖區中

  2. 使用另一個線程來解析消息

方法3:

  1. 使用一個線程讀取串行端口,提取有效消息,然后阻塞直到該消息被處理為止,利用QtSerialPort的內部讀取緩沖區來緩沖傳入的數據

方法4:

  1. 使用主線程異步讀取串行端口,提取一條有效消息,並為每條消息生成一個新線程來處理它們

方法1,2和3的區別在於,一般工作負載被划分為多個線程,盡管我不知道哪個是最好的。

我當前正在使用方法4,由於產生了大量線程,並且每次我移動或與GUI交互時,串行通信都會停止,方法4效率極低,並且在低端計算機上無法很好地工作。 為每條消息生成一個線程也會使消息的順序不確定,這到目前為止並不是一個主要問題。

是否還有其他方法,每種方法各有利弊(如果有),哪種方法最好? 謝謝!

編輯:在主線程中處理消息的一個問題是與GUI交互(甚至移動窗口)將阻止消息處理功能。 有沒有辦法解決?

我認為使用多線程可以獲得兩個主要優點:

  1. 避免由於GUI處理例程被串行端口處理例程拖延而導致不良的GUI性能
  2. (也許更重要)當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.

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