Qt QStateMachine同步问题:未在启动信号上设置初始状态

Dav*_*ond 1 c++ qt state-machine qstatemachine

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

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

具体来说,这是为了维护邻居.在设备XI中,获取一条消息,其中邻居Y表示你好.这导致邻居X为这个新邻居Y malloc一个邻居状态机.这使得邻居状态机然后调用QStateMachine :: start();

现在,在启动此状态机之后,我需要继续处理此hello消息.所以起初我在做:

QStateMachine::start( ) ;
emit event 1 ;
Run Code Online (Sandbox Code Playgroud)

我的理解是这不起作用,因为start是一个异步调用,所以状态机直到启动完成后才开始.这引出了我的第一个问题.

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

认为这是问题我通过将函数连接到状态机启动信号来稍微改变了我的代码.然后,如果状态机未启动,我将代码更改为队列事件,并在调用启动信号后处理此挂起事件队列(并将其发送到状态机).

事实证明,当我开始发出信号时,初始状态仍未设置.例如QStateMachine :: configuration().enctains(initialstate)== false.这引出了我的第二个更大的问题.

2)为什么在发出启动信号时我不处于初始状态.

这里的事件顺序是:

  1. 创建状态机
  2. 设置初始状态
  3. 启动状态机
  4. 接收活动1
  5. 由于没有启动队列事件1
  6. 开始信号rxed
  7. 流程事件1
  8. 既然是未知状态什么都不做
  9. 接收活动1
  10. 流程事件1
  11. 现在处于状态A.过渡到状态B.

顺序应该是:

  1. 创建状态机
  2. 设置初始状态
  3. 启动状态机
  4. 接收活动1
  5. 由于没有启动队列事件1
  6. 开始信号rxed
  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.什么都不做.

ale*_*sdm 6

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

bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
                                   signalEventGenerator->metaObject()->methodOffset());
Run Code Online (Sandbox Code Playgroud)

对于要接收的"事件1",机器必须已经处于对该信号作出反应的状态.即使它是一个排队的连接,插槽也会排队,但只有在接收到信号后才会排队,但由于此时还没有连接,所以它不会排队.

要解决您的问题,您可以在发出信号之前等待机器处于"状态A":

machine->start();
qApp->processEvents();
emit event1();
Run Code Online (Sandbox Code Playgroud)

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

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

started之前被设定的初始状态(如源代码),它可以是有益的,如果你有初始化设置任何状态之前做信号被发射.如果需要等待初始状态,可以使用该信号QState::entered.