2012-04-08 16 views
1

QtのQStateMachineの問題を理解しようとしています。私はQStateMachineの基本的な理解に非常に興味を持っています。Qt QStateMachine同期の問題:開始信号に初期状態が設定されていません

状態AとBとイベント1を持つ状態マシンを考えてみましょう。イベント1はAからBへとあなたを導きます。Aは初期状態です。

特にこれは近隣を維持するためです。デバイスXでは、隣人Yがこんにちはと言うメッセージを受け取ります。これにより、隣人Xはこの新しい隣人Yの隣人状態マシンをmallocする。これは隣人状態マシンを作成し、QStateMachine :: start()を呼び出す。

この状態マシンの起動後、このhelloメッセージの処理を続行する必要があります。だから、最初は私がやっていた:

私の理解では、スタートが非同期呼び出しで、実行され、開始後までその状態マシンがその最初のスタートではないので、これは動作しませんです。それが私の最初の質問につながります。

1)したがって、状態マシンの開始はqappイベントキューに入れられますが、非同期呼び出しも発行されません。イベント1は開始後にイベントキューに入れられないので、初期状態になるわけではありませんか?または、非同期呼び出しではないのですか?

これは問題だと思っていましたが、機能をステートマシン起動信号に接続することでコードを少し変更しました。ステートマシンが起動されていない場合に、イベントを待ち行列に入れるようにコードを変更し、開始されたシグナルが呼び出された後、この待ち行列のイベントを処理してステートマシンに出力します。

これは、信号を開始すると初期状態がまだ設定されていないことがわかります。例えばQStateMachine :: configuration().contains(initialstate)== falseです。これは私の第二の大きな問題につながります。

2)なぜ開始信号が放射されるかは、初期状態ではない。

ここで一連のイベントは次のとおりです。

  1. は、キューイベント1
  2. 起動していないので
  3. 設定し、初期状態
  4. スタートステートマシン
  5. がイベント1
  6. を受信ステート・マシンを作成します。
  7. 開始信号rxed
  8. プロセスイベント1
  9. 不明の状態で何も
  10. はB.を状態にA.遷移に今イベント1
  11. プロセスイベント1
  12. を受信しないでくださいので、

シーケンスは次のようになります。

  1. は、キューイベント1
  2. を開始していないので、イベント1
  3. を受信
  4. 設定し、初期状態
  5. スタートステートマシンステートマシンを作成します。開始信号rxed
  6. のプロセスイベント1
  7. は今すぐ状態Bは何もしないでB.
  8. がイベントに1
  9. プロセスイベント1
  10. を受信状態に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

関連する問題