2012-04-08 3 views
1

Итак, я пытаюсь понять проблему с QStateMachine Qt, и я надеюсь, что кто-то может помочь объяснить, почему это происходит. Меня очень интересует фундаментальное понимание QStateMachine, а не просто исправление.Проблемы с синхронизацией Qt QStateMachine: начальное состояние не установлено на начальном сигнале

Сначала рассмотрим машину состояний с состояниями A, B и событием 1. Событие 1 приводит вас от A до B. A - это начальное состояние.

В частности, это касается поддержания соседей. В устройстве X я получаю сообщение, в котором соседка Y приветствует. Это приводит к тому, что сосед X должен malloc соседний конечный автомат для этого нового соседа Y. Это делает соседний конечный автомат, а затем вызывает QStateMachine :: start();

Теперь, после запуска этого состояния, мне нужно продолжить обработку этого приветственного сообщения. Так что сначала я делал:

Я понимаю, что это не будет работать, потому что запуск является асинхронной вызов и поэтому состояние машина не в ее первоначальном запуске, пока после запуска будет сделано. Это приводит меня к моему первому вопросу.

1) Итак, запуск конечного автомата помещается в очередь событий qapp, но не вызывает асинхронный вызов? Не будет ли событие 1 помещено в очередь событий после начала и, следовательно, это не означает, что мы будем в исходном состоянии? Или это не асинхронный вызов?

Подумав, что это была проблема, я немного изменил свой код, подключив функцию к сигналу запуска конечного автомата. Затем я изменил свой код, чтобы поставить очередь событий, если конечный автомат не запущен, и я обрабатываю эту очередь ожидающих событий (и выдает их на конечный автомат) после вызова начального сигнала.

Ну, оказывается, что начальное состояние STILL не установлено, когда я начинаю сигнал. например QStateMachine :: configuration() .contains (initialstate) == false. Это приводит меня к моему второму и большему вопросу.

2) Почему, когда начальный сигнал испускается, я не в исходном состоянии.

Последовательность событий здесь является:

  1. Создать государственную машину
  2. Установить начальное состояние
  3. Start состояние машины
  4. Получить событие 1
  5. Поскольку не началось событие очереди 1
  6. Начальный сигнал rxed
  7. Процесс события 1
  8. Поскольку не неизвестное состояние ничего сделать
  9. получить событие с 1
  10. событие процесса 1
  11. сейчас в состоянии А. перехода в состояние B.

Последовательность должна быть:

  1. Создать государственную машину
  2. Установить начальное состояние
  3. Start состояние машины
  4. Получить событие 1
  5. Поскольку не началось событие очереди 1
  6. Начальный сигнал rxed
  7. Процесс события 1
  8. Сейчас состояние А. перехода в состояние B.
  9. Получить событие 1
  10. процесса событие 1
  11. Сейчас состояние B. Ничего не делать.

Или событие лучше, если бы мне не пришлось останавливать мероприятие. Я хотел бы сделать это:

  1. Создать государственную машину
  2. Установить начальное состояние
  3. Start состояние машины
  4. Получить событие 1
  5. событие Процесс 1
  6. Сейчас состояние А. Переход к состояние B.
  7. Событие приема 1
  8. Технологическое событие 1
  9. Теперь состояние B. Не делайте ничего.

ответ

6

Переходные сигналы подключаются только после изменения состояния (в QStateMachinePrivate::registerSignalTransition), и соединение не в очередь соединение:

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

Для «события 1», который будет получен, машина должна быть уже в состоянии, реагирующем на этот сигнал. Даже это было соединение в очереди, слот был бы поставлен в очередь, но только после того, как был получен сигнал, а это еще не так, поскольку в данный момент соединение отсутствует.

Чтобы решить вашу проблему, вы можете ждать машины находится в «состоянии А» перед испусканием сигнала:

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

Или вы можете задержать эмиссию сигнала и поставить его в очередь после того, как другие уже поставлены в очередь операций:

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

started сигнал испускается до исходного состояния устанавливается (в соответствии с исходным кодом), который может быть полезным, если у вас есть инициализацию сделать, прежде чем любое состояние устанавливается. Если вам нужно дождаться начального состояния, вы можете использовать сигнал QState::entered.

+0

Спасибо, что работает как шарм. Я до сих пор не понимаю, почему, когда вызывается начальный сигнал, мы не находимся в исходном состоянии, но, на мой взгляд, это не имеет значения. Очень признателен. –

+0

Я бы не рекомендовал шаблон с помощью qApp-> processEvents().Причина этого заключается в том, что вы не только собираетесь обрабатывать интересующее вас событие, но и все, что есть в очереди, поэтому вам придется обрабатывать дополнительные случаи. Такой вид гнездования никогда не является хорошей идеей ИМО. – mhstnsc

 Смежные вопросы

  • Нет связанных вопросов^_^