我正在开发一个基于Python的闪亮应用程序,用于通过串行传输线驱动流体泵。配置具有设定幅度和运行时间的流量曲线后,可以通过按操作按钮“p1”启动串行传输。
我面临的问题是与按钮“p1”相关的
reactive.event(input.p1)
内部缺乏反应性:我想确保通过单击“p1”开始传输,从而触发reactive.event(input.p1)
可以随时通过单击“终止” p2”。
但是,当前的实现会导致
reactive.event(input.p2)
中的停止消息排队并在 reactive.event(input.p1)
中的传输结束后发送。
我该如何解决这个问题?有什么方法可以确保我的程序仍然对其他输入做出反应?我希望单击“p2”后立即停止传输。 两个按钮的实现都放在下面。
@reactive.Effect
@reactive.event(input.p1)
def _():
y = yg.get() # fetch np.array y from reactive value yg, numbers in y correspond to driving voltages
for e in y: # iterate over array
msg = "1:1:"+str(e)+":100" # formatted string containing the driving voltage
#print(msg) # print to console in debug mode
ser.write(bytes(msg,'utf-8')) # send the formatted string
t0 = time.time() # time stamp
while(((time.time()-t0)<=2)): # next driving voltage should be transmitted after 2 seconds
pass
ser.write(bytes("0:1",'utf-8')) # stops the pump after transmission has ended
@reactive.Effect
@reactive.event(input.p2)
def _():
#print("1:0")
ser.write(bytes("0:1",'utf-8')) # Stop the pump
好吧,我通过线程创建计时器成功解决了这个问题。就我个人而言,我认为答案是,就其本身而言,不可能在循环内保留反应性。我尝试了各种实现,包括@phili_b 建议的实现。但没有什么真正迫使程序退出 while 循环,该循环是通过单击按钮 p2 在与按钮 p1 相关的反应事件中调用的。
这是对我有用的解决方案:
# This function may very well be included into the one below,
# but in this case this structure serves me well
# function takes a number, forms the message string and puts it on the serial port
def transmit(e):
msg = "1:1:"+str(e)+":100"
#print(msg)
ser.write(bytes(msg,'utf-8'))
# This is the main function that is being threaded. Loop iterates over array y
# every 2 seconds until either end of y or the threading Event sflag is triggered
def rtimer(y,sflag): # Timer calls this function
i = 0
while i<np.size(y) and not sflag.is_set():
transmit(y[i])
i+=1
time.sleep(2) # 2 second interval between transmissions
# p1-button calls this function
@reactive.Effect()
@reactive.event(input.p1)
def _():
y = yg.get()
sflag.clear() # clear slfag in case it has been triggered prior
timer_thread = th.Thread(target=rtimer,args=[y,sflag]) # threading is imported as th
timer_thread.start()
# p2-button calls this function
@reactive.Effect()
@reactive.event(input.p2)
def stop():
#print("1:0")
sflag.set()
ser.write(bytes("1:0",'utf-8'))
我知道这是一种解决方法,而不是我在OP中建议的实施的修复。尽管代码现在可以实现我想要的功能,但我仍然很好奇是否有办法使原始代码能够工作。 因此,我愿意让这个帖子继续存在,以留出讨论的空间,特别是因为它有赏金。我很想知道本质上是否有可能处理循环似乎对程序造成的限制。