【问题标题】:Emitting a signal to one object in a set dynamically动态地向集合中的一个对象发出信号
【发布时间】:2012-01-08 22:09:21
【问题描述】:

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

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

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

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

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

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

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

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

问候

普莱斯

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

(app)(发射器)(接收器)物理设备

【问题讨论】:

    标签: c++ qt dynamic observer-pattern qt-signals


    【解决方案1】:

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

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

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

    【讨论】:

    • 我的问题措辞很糟糕,并对其进行了更新以澄清一点。 1)是的,但现在我只关心从应用程序到接收器的信号流。 2) 接收者相同但不共享数据。 ACE 似乎对此可能有点矫枉过正。
    • @Pris Reactor 仍然可以工作,即使它不是 ACE 我正在调整答案。
    【解决方案2】:

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

    如果您被限制在 Qt 信号/槽系统之间,那么您的具体问题的答案:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-03
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      相关资源
      最近更新 更多