1

我有一个情况,我有一个发射器对象和一组接收器。接收器属于同一类,实际上代表一组相同类型的设备。我正在使用 Qt 框架。

  • 发射器本身首先收到一个信号,要求从其中一个设备获取信息。

  • 在相应的插槽中,发射器必须检查哪些接收器“准备好”,然后发送自己的信号以向其中一个设备请求数据(以先准备好的为准)。

发射器接收信号的速度非常快,大约为毫秒。我可以想到三种安全地从其中一个设备请求数据的方法(这些设备存在于它们自己的线程中,所以我需要一个线程安全机制)。设备的数量不是静态的,而是可以变化的。设备的总数非常少(肯定在 5-6 个以下)。

1)在添加或删除设备时连接到所有设备。发出一个请求,并让设备对象自己使用某些特定的设备标签过滤该请求是否是针对他们的。这种方法很好,因为发生检查的请求槽将在专用线程的上下文中执行,但随着设备数量的增加而浪费。

2)当需要发送请求时,动态连接和断开与发射器中的对象。

3) 在需要发送请求时使用 QMetaObject::invokeMethod()。

性能很重要。有谁知道哪种方法是“最好的”,或者是否有更好的方法?

问候

棱镜

注意:澄清:发射器从应用程序获取信号,通过查询设备获取信息。疯狂的 ASCII 艺术去:

(app)<---->(发射器)<------>(接收器)<--|-->物理设备

4

2 回答 2

0

根据您提供的信息,我仍然建议Reactor实施。如果您不使用 ACE,那么您可以实现自己的。基本架构如下:

  1. 用于select在收到来自 App 的信号或数据时唤醒。
  2. 如果发送列表上有一个套接字准备好,那么您只需选择一个并向其发送数据
  3. 发送数据时,Receiver会将自身从可用的套接字/处理程序集中删除
  4. 当处理数据时,它Reciever会将自身重新注册到可用接收者列表中。

我建议的原因ACE是因为它具有最简单的Reactor模式实现之一。

于 2012-01-08T23:05:07.227 回答
0

我在这里很有趣,这是多线程环境。

如果您仅限于 Qt 信号/插槽系统,那么您的具体问题的答案:

1)绝对不是要走的路。在发出Emitter的事件总数等于Receivers设备的线程事件循环的数量的情况下,一旦线程到达这些事件,将发生相同数量的插槽调用。即使大多数人只是if(id!=m_id) return;在第一行就输了,但在 Qt 的核心中发生了大量的事情。在您的一个由信号引发的插槽中放置一个断点,Qt::QueuedConnection并通过查看实际的堆栈跟踪来验证这一点。它通常至少有 4 次调用深度xyEventLoop::processEvents(...),因此“刚返回”在时间上绝对不是“免费”。

2)不确定Qt的内部实现实际上是如何,但据我所知,连接和断开连接很可能包括将发送方和接收方插入和删除到一些列表中,这些列表很可能通过QMutex锁定访问。- 在时间上也可能是“昂贵的”,快速连接和断开连接绝对不是最佳实践。

3) 可能是您能找到的仍在使用 Qt 的单槽系统的“时间成本最低”的解决方案。

可选)看看QSignalMapper。它专为您计划在选项 1) 中执行的操作而设计。

有更多的最佳解决方案可以在您的Emitterand之间进行通信Receivers,但作为最佳实践,我会首先选择最易于使用和快速实施的选项,但有机会获得足够快的运行时间(即选项 3 )。)。然后,完成后,看看它是否满足您的性能要求。如果没有,只有到那时,才考虑在数据提供者中使用带有互斥锁的共享内存 - 数据消费者架构(Emitter线程在循环列表中快速发布请求数据,而Receiver线程只要有时间就读取它们,然后将结果发布回来类似的方式,而Emitter线程不断轮询完成的结果。)

于 2016-06-08T11:19:28.743 回答