2012-04-08 2 views
1

Qt의 QStateMachine에 대한 문제를 이해하려고하는데 누군가 이런 일이 발생하는 이유를 설명하기를 바랍니다. 저는 단지 수정보다는 QStateMachine에 대한 기본적인 이해에 매우 흥미가 있습니다.Qt QStateMachine 동기화 문제 : 시작 신호에 초기 상태가 설정되어 있지 않습니다.

먼저 상태 A와 B 및 이벤트 1이있는 상태 시스템을 고려하십시오. 이벤트 1은 A에서 B로 연결됩니다. A는 초기 상태입니다.

특히 이웃을 유지 관리하기위한 것입니다. 장치 X에서 나는 이웃 Y가 인사하는 메시지를 받는다. 이것은 이웃 X가이 새로운 이웃 Y에 대한 이웃 상태 머신을 malloc하게합니다. 이것은 이웃 상태 머신을 만들고 QStateMachine :: start()를 호출합니다;

이제이 상태 시스템이 시작된 후에이 hello 메시지를 계속 처리해야합니다. 처음에는 그래서 내가 뭘하고 있었 :

QStateMachine::start() ; 
emit event 1 ; 

나의 이해는 시작은 비동기 호출입니다 그래서 상태 기계는 시작이 완료 할 때까지 초기 시작에 있지 않기 때문에이 작동하지 것이다. 그것은 저의 첫 번째 질문으로 이어집니다.

1) 따라서 상태 시스템 시작은 qapp 이벤트 대기열에 배치되지만 비동기 호출도 방출하지 않습니다. 이벤트 1은 시작 후에 이벤트 대기열에 배치되지 않으므로 우리가 초기 상태가된다는 의미가 아닙니까? 아니면 비동기 호출이 아닌 방출입니까?

이것은 내가 상태 코드 시작 신호에 함수를 연결하여 코드를 약간 변경 한 문제라고 생각합니다. 그런 다음 상태 시스템이 시작되지 않고 시작된 신호가 호출 된 후 보류중인 이벤트 대기열을 처리하고 (상태 시스템에 이벤트를 방출하는 경우) 이벤트를 큐에 대기하도록 코드를 변경했습니다.

그럼 시작 신호가 들리면 아직 초기 상태가 설정되어 있지 않습니다. 예 : QStateMachine :: configuration() .contains (initialstate) == false입니다. 이것은 제 두 번째 큰 질문으로 이어집니다.

2) 시작 신호가 출력되는 시점이 초기 상태가 아닌 이유는 무엇입니까?

여기 이벤트의 순서는 다음과 같습니다

  1. 시작되지 때문에 이벤트 1
  2. 수신 상태 머신
  3. 설정 초기 상태
  4. 시작 상태 머신
  5. 만들기 큐 이벤트 1
  6. 시작된 신호 rxed
  7. 프로세스 이벤트 1
  8. 상태 A. 전환 1
  9. 프로세스 이벤트를 아무것도
  10. 수신 이벤트를 이제 1
  11. 을 알 수없는 상태하지 않는다된다 B.를 명시하기 때문에

순서는 다음과 같아야합니다

  1. 상태 머신을 생성
  2. 설정 초기 상태
  3. 시작 상태 머신
  4. 시작되지 때문에 이벤트 1
  5. 수신 큐 이벤트 1
  6. 시작 신호 rxed
  7. 개 프로세스 이벤트 1
  8. 지금 현재 상태 B. 아무것도 할 것입니다 B.
  9. 이벤트 1
  10. 프로세스 이벤트 1
  11. 수신 상태로 상태 A. 전환이다.

또는 이벤트를 대기열에 추가하지 않아도됩니다. 나는이 작업을 수행 할 수 있으면 좋겠다 :

  1. 상태 머신을 생성
  2. 설정 초기 상태
  3. 시작 상태 머신
  4. 수신 이벤트 1
  5. 프로세스 이벤트 1
  6. 지금 상태 A. 전환에이다 상태 B
  7. 수신 이벤트 1
  8. 프로세스 이벤트 1
  9. 이제는 상태 B입니다. 아무 것도하지 않습니다.

답변

6

전환 신호 만 (QStateMachinePrivate::registerSignalTransition)에서 상태 변경 후 접속 연결은 대기 연결 아니다 같다 : "이벤트 1"을 수신 할

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

기계가 이미 있어야 그 신호에 반응하는 상태. 그것은 대기열에있는 연결 일지라도, 슬롯은 대기열에 있지만 신호가 수신 된 후에 만 ​​대기합니다.이 지점은 아직 연결이 없기 때문에 아닙니다.

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

아니면 신호 방출을 지연하고 다른 이미 대기중인 작업 후 대기열 수 :

문제를 해결하기 위해, 당신은 기계 기다릴 수는 신호를 방출하기 전에 "상태 A"에 있습니다 : 초기 상태가 어떤 상태로 설정되기 전에 초기화 할 수있는 경우 유용 할 수있다 (소스 코드)에 따라 설정되기 전에

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

started 신호가 방출된다. 초기 상태를 기다려야하는 경우 신호 QState::entered을 사용할 수 있습니다.

+0

고마워요, 그것은 매력처럼 작동합니다. 나는 아직도 시작된 신호가 호출되었을 때 우리가 초기 상태가 아닌 이유를 이해하지 못한다. 그러나 나는이 시점에서 중요하지 않다고 생각한다. 매우 감사. –

+0

qApp-> processEvents()를 사용하여 패턴을 사용하지 않는 것이 좋습니다.그 이유는 관심있는 이벤트를 처리 할뿐만 아니라 대기열에있는 모든 항목을 처리하므로 추가 사례를 처리해야하기 때문입니다. 이러한 중첩은 결코 좋은 아이디어가 아닙니다. – mhstnsc