我目前正在研究分层状态机(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 | +---------------------------------------------------------------+
状态机可以将事件发布到self,但这有特殊的用途,例如将较长的运行到完成(RTC)步骤分解为较短的部分。您可能想这样做,以便在过长的RTC步骤之间对系统中的其他状态机(或更常见的活动对象)进行调度。
具体到你的例子,在这种情况下,我会尽量避免向自己发布事件。通常,当人们把状态图和流程图混淆时,我会看到他们这样做。状态图需要事件从一个状态转换到另一个状态。流程图在框中指定的计算完成后自动从一个处理框转换到另一个处理盒。显然,当你向自己发布事件时,你就把状态图变成了流程图。所以,你真的需要一个流程图,而不是状态图,因为你不需要等待任何事情。您可以保持全速处理。
你也可以这样看。事件的目的是向状态机提供新的信息。这就是状态机"学习"的方式。但当你把事件发布给自己时,你不会获得任何新的知识。你所需要的所有知识都已经通过最初的"真实"事件提供了。因此,您有足够的信息在一个转换中执行所有这些处理,而不是在许多"状态"之间传播,这些"状态"实际上是这种漫长处理的阶段。