我目前正在研究分层状态机(UML状态机,状态图等),我不清楚以下内容:
在转换期间将事件推送到机器自己的事件队列,并且从有效状态推送事件队列,如果是,是否在实践中安全使用或是否应该避免?这样做是否有某些影响(至少是实施怪癖,正交区域发挥作用时的问题,或类似情况)?
我将用两台虚拟机器说明问题:
以下机器将处于状态A
,等待事件A_to_B
,然后通过将事件作为转换操作调度进入无限循环:
+-----+ +-----+ +-----+
| A | A_to_B / | B | B_to_C / | C |
|-----| dispatch B_to_C |-----| dispatch C_to_A |-----|
O---->| +------------------->| +------------------->| |
| | | | | |
+-----+ +-----+ +-----+
^ C_to_A / |
| dispatch A_to_B |
+-----------------------------------------------------+
通过将事件作为输入操作调度,以下机器将立即进入无限循环:
+-------------------+ +-------------------+ +-----+
| A | | B | | C |
|-------------------| A_to_B |-------------------| B_to_C |-----|
O---->| on entry: +---------->| on entry: +---------->| |
| dispatch A_to_B | | dispatch B_to_C | | |
| | | dispatch C_to_A | | |
+-------------------+ +-------------------+ +-----+
^ |
| C_to_A |
+---------------------------------------------------------------+
答案 0 :(得分:6)
状态机可以将事件发布到自己,但这有特殊用途,例如将更长的运行完成(RTC)步骤分解为更短的部分。您可能希望这样做以在您太长的RTC步骤之间启用系统中其他状态机(或更常见的活动对象)的调度。
具体到您的示例,我会尽量避免在这种情况下向自己发布事件。通常我会看到人们在将状态图与流程图混淆时执行此操作。状态图需要事件从一个状态转换到另一个状态。在完成框中指定的计算后,流程图自动从一个处理框转换到另一个处理框。显然,当您向自己发布事件时,您将状态图转换为流程图。所以,你真的需要一个流程图,而不是状态图,因为你真的不需要等待任何事情。你继续全速处理。
您也可以这样查看。事件的目的是为状态机提供新信息。这就是状态机“学习”的方式。但是当你向自己发布事件时,你不会获得任何新知识。您需要的所有知识都已经由原始的“真实”事件提供。因此,您有足够的信息在一次转换中执行所有这些处理,而不是将其分布在许多“状态”中,这实际上是这种冗长处理的阶段。