繁体   English   中英

动态向一组物体发射信号

[英]Emitting a signal to one object in a set dynamically

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

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

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

发射器非常快地接收信号,大约为毫秒。 我可以考虑通过三种方式仅从其中一台设备安全地请求数据(这些设备位于各自的线程中,因此我需要一种线程安全的机制)。 设备的数量不是静态的,并且可以更改。 设备总数非常小(肯定在5-6以下)。

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

2)需要发送请求时,即时连接发射器内的对象并与之断开连接。

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

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

问候

普里斯

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

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

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

如果您被限制在Qt信号/插槽系统之间,则针对特定问题的答案:

1)绝对不是要走的路。 Emitter发出的事件总数等于Receivers数量的事件将排队等待设备的线程事件循环,然后一旦线程到达这些事件,将发生相同数量的插槽调用。 即使大多数丢失的只是if(id!=m_id) return; 在他们的第一行中,它在Qt的核心中发生了大量事情。 将一个断点放在Qt::QueuedConnection信号引起的插槽中,并在实际的堆栈跟踪中进行验证。 通常,它至少要从xyEventLoop::processEvents(...)进行至少4次调用,因此就时间而言,“仅返回”绝对不是“免费的”。

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

3)可能是您发现仍在使用Qt的单槽系统的最“昂贵的按时”解决方案。

(可选)看看QSignalMapper 它完全按照您计划在选项1)中执行的操作而设计。

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

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

  1. 从应用程序接收到信号或数据时,请使用select唤醒。
  2. 如果发送列表上已准备好套接字,则只需选择一个套接字并发送数据即可
  3. 发送数据后, Receiver会将自己从可用的套接字/处理程序集中删除
  4. 处理数据后,接收方Reciever自己重新注册到可用收件人列表中。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM