我有一个相当复杂的应用程序,涉及一个 GUI 前端和几个其他类,其中几个是基于优秀pytransitions库的状态机。应用程序在不同的时间挂起,并且是多线程的,很难调试,但我在这里复制了一个最小的例子:
from transitions import Machine
import time
States = ["OFF", "ON"]
Transitions = [{"trigger": "PowerUp", "source": "OFF", "dest": "ON"}]
class GUI:
def __init__(self):
self.machine1 = Machine_1(self)
self.machine2 = Machine_2(self)
def on_button_pressed(self):
self.machine2.trigger("PowerUp")
self.machine1.trigger("PowerUp")
class Machine_1:
def __init__(self, parent):
self.parent = parent
self.fsm = Machine(model=self, states=States, transitions=Transitions, initial="OFF")
def on_enter_ON(self):
print("machine1 is on!")
self.parent.machine2.signal = True
class Machine_2:
def __init__(self, parent):
self.parent = parent
self.fsm = Machine(model=self, states=States, transitions=Transitions, initial="OFF")
self.signal = False
def on_enter_ON(self):
print("machine2 waits for machine1 ...")
while self.signal is False:
time.sleep(0.1)
print("machine2 on!")
即当machine1“打开”时,它向machine2发送一个信号。machine2 必须等待此信号,然后才能执行其“开启”状态的逻辑。
使用 Python REPL 作为主循环:
>>> import test
>>> gui = test.GUI()
>>> gui.machine1.state
'off'
>>> gui.machine2.state
'off'
>>> gui.on_button_pressed()
machine2 waits for machine1 ...
(never returns)
machine2 卡在其 while 循环中,等待来自 machine1 的信号,该信号永远不会到达,因为 machine1 从未被触发。
如果我重新排序触发器序列gui.on_button_pressed():
self.machine1.trigger("PowerUp")
self.machine2.trigger("PowerUp")
...一切正常:
>>> gui.on_button_pressed()
machine1 is on!
machine2 waits for machine1 ...
machine2 is on!
这里发生了什么?该trigger()方法应该阻止吗?它是否记录在某处,何时返回?还是我on_enter_state以不受支持的方式使用回调?我应该使用推荐的模式吗?