如何在反应函数内保留程序反应性?

问题描述 投票:0回答:1

我正在开发一个基于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
python reactive-programming py-shiny
1个回答
0
投票

好吧,我通过线程创建计时器成功解决了这个问题。就我个人而言,我认为答案是,就其本身而言,不可能在循环内保留反应性。我尝试了各种实现,包括@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中建议的实施的修复。尽管代码现在可以实现我想要的功能,但我仍然很好奇是否有办法使原始代码能够工作。 因此,我愿意让这个帖子继续存在,以留出讨论的空间,特别是因为它有赏金。我很想知道本质上是否有可能处理循环似乎对程序造成的限制。

© www.soinside.com 2019 - 2024. All rights reserved.