0

我目前正在(重新)设计一个由几个部分组成的系统:

  • 第一部分是一个实体,它(异步)从源获取帧并在每次帧准备好时触发一个事件——通过 Qt 信号。
  • 第二部分是实时显示帧的 GUI,并通过插槽连接到上述信号
  • 最后一部分是帧处理器,它的行为最好用顺序算法(while、for 等)来描述,并有可能响应来自 GUI 的几种信号。

主要问题是是否有组织此类代码的最佳实践

我想出但不太喜欢的解决方案是:运行 4 个线程。

  • 通过 Qt 信号与其他 3 个线程进行通信的 GUI 线程
  • 帧源线程在每个帧可用性上发出信号。
  • 帧组织器线程,它根据信号存储帧并使用 QWaitCondition 通知帧处理器线程。
  • 从帧管理器调用 getNextFrame() 的帧处理器线程。

但我觉得这不是一个好的解决方案,可能是由于混合了不同的范例(等待条件和信号)。此外,等待条件可能会导致事件处理队列不足。

4

1 回答 1

1

没有必要使用QWaitCondition. 线程应该是裸的(非派生的)QThreads。把你所有的代码QObjects都移到那些线程中。帧组织器只是将信号发送到帧处理器。通过将事件发布到线程的事件循环来跨线程边界传递信号。这些事件循环在内部使用同步原语(互斥体)来序列化访问,因此无需在那里重新发明轮子。QThread 的默认实现run()只是简单地旋转一个事件循环,因此除了实例化线程并启动它之外,您不需要做任何事情。

您的代码应该在 GUI 线程中实例化所有 QObject 的情况下运行,但性能可能会降低。当您的基准测试显示哪些对象受 CPU 限制时,将它们移动到单独的线程中。这条规则有一个可悲但必要的例外:如果您的相机代码只能使用相机驱动程序提供的阻塞 API(等待某事而不是异步报告某事的 API),那么您别无选择,只能为此牺牲一个线程. 除了这种专用的阻塞变通线程之外,您的应用程序应该使用与可用内核一样多的线程(QThread::idealThreadCount())。您将实例化多达该数量的线程,并在这些线程中随机或以循环方式分配 QObject。再次——只移动受 CPU 限制的 QObject。使用非阻塞 API(网络!)的 IO 绑定对象不需要这种处理。Sane 设备驱动程序(例如来自http://www.ftdichip.com/的)公开异步事件通知,可以通过QWinEventNotifier. 它是 Qt 4.x 中的私有 API,但尽管如此,它仍然可以正常工作。

很多常见的API都被阻塞了,这真是令人遗憾。数据库驱动程序就是一个典型的例子。例如,我最终移植了 mysql 客户端驱动程序来使用QTcpSocket,这样数据库就不会阻塞使用它的线程。

于 2012-07-01T15:27:16.753 回答