c++ - Qt QStateMachine 同步问题 : Initial State not set on Started Signal

标签 c++ qt state-machine qstatemachine

所以我试图了解 Qt 的 QStateMachine 的一个问题,我希望有人能帮助解释为什么会这样。我对 QStateMachine 的基本理解非常感兴趣,而不仅仅是修复。

首先考虑具有状态 A、B 和事件 1 的状态机。事件 1 将您从 A 带到 B。A 是初始状态。

具体来说,这是为了维护邻居。在设备 X 中,我收到一条消息,其中邻居 Y 打招呼。这会导致邻居 X 为这个新邻居 Y 分配一个邻居状态机。这会创建邻居状态机,然后调用 QStateMachine::start();

现在,在这个状态机启动后,我需要继续处理这个问候消息。所以一开始我在做:

QStateMachine::start( ) ;
emit event 1 ;

我的理解是这是行不通的,因为启动是一个异步调用,因此状态机在启动完成后才处于初始启动状态。这引出了我的第一个问题。

1) 所以状态机启动被放置在 qapp 事件队列中但也没有发出异步调用?事件1不会在开始后被放入事件队列中,那不就意味着我们将处于初始状态吗?或者发出不是异步调用?

认为这是问题所在,我通过将一个函数连接到状态机启动信号来稍微更改我的代码。然后,如果状态机未启动,我更改代码以对事件进行排队,并在调用启动信号后处理此待处理事件队列(并将它们发送到状态机)。

当我收到开始信号时,结果表明初始状态仍未设置。例如QStateMachine::configuration().contains(initialstate) == false。这引出了我的第二个也是更大的问题。

2)为什么当发出启动信号时我不在初始状态。

这里的事件顺序是:

  1. 创建状态机
  2. 设置初始状态
  3. 启动状态机
  4. 接收事件1
  5. 因为未开始队列事件 1
  6. 接收到开始信号
  7. 处理事件 1
  8. 因为是未知状态什么都不做
  9. 接收事件1
  10. 处理事件 1
  11. 现在处于状态 A。过渡到状态 B。

顺序应该是:

  1. 创建状态机
  2. 设置初始状态
  3. 启动状态机
  4. 接收事件1
  5. 因为队列事件 1 未开始
  6. 接收到开始信号
  7. 处理事件 1
  8. 现在是状态 A。过渡到状态 B。
  9. 接收事件1
  10. 处理事件 1
  11. 现在是状态 B。什么都不做。

或者更好的事件我希望我不必排队事件。我希望我能做到这一点:

  1. 创建状态机
  2. 设置初始状态
  3. 启动状态机
  4. 接收事件1
  5. 处理事件 1
  6. 现在是状态 A。过渡到状态 B。
  7. 接收事件1
  8. 处理事件 1
  9. 现在是状态 B。什么都不做。

最佳答案

转换信号仅在状态更改后连接(在 QStateMachinePrivate::registerSignalTransition 中)并且连接不是排队连接:

bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
                                   signalEventGenerator->metaObject()->methodOffset());

要接收“事件 1”,机器必须已经处于对该信号使用react的状态。即使它是排队连接,插槽也会排队,但只有在收到信号后才会排队,因为此时还没有连接。

要解决您的问题,您可以等待机器处于“状态 A”,然后再发出信号:

machine->start();
qApp->processEvents();
emit event1();

或者你可以延迟信号发射并在其他已经排队的操作之后排队:

machine->start();
QTimer::singleShot(0, emitter, SIGNAL(event1()));
// or
QMetaObject::invokeMethod(emitter, "event1", Qt::QueuedConnection);

started 信号在设置初始状态之前发出(根据源代码),如果您在设置任何状态之前需要进行初始化,这会很有帮助。如果需要等待初始状态,可以使用信号QState::entered

关于c++ - Qt QStateMachine 同步问题 : Initial State not set on Started Signal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10059721/

相关文章:

c++ - QTableView - 不允许用户编辑单元格

c++ - 使用 QTimer 显示定时器

python - 如何在 Pytransitions 中向现有状态对象添加标签?

c++ - 在 C++ 状态机中实现事件条件

python - 如何使 PySide.QtCore.QTimer.singleShot 调用其超时方法

c++ - C++ 中的嵌套隐式转换

c++ - 从 C++ 字符串中删除特殊字符(' 和 - 除外)

c++ - std::unordered_map::operator[] - 为什么有两个签名?

c# - 使用无状态的基本状态机设置

C++ DGRAM套接字获取RECEIVER地址