繁体   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