Python 在线程类方法中使用Event.set()触发GPIO输入中断时暂停线程
大家好,我正在尝试调用thread类中的一个方法,该方法应该在该线程中设置一个事件标志,导致该线程在设置事件时停止运行。当前代码可以工作,并调用函数,但事件标志似乎不会在线程内部触发 线程负责在按下GUI上的按钮时运行的操作,但如果设置了事件,则不应运行该操作 我的代码的最低版本:Python 在线程类方法中使用Event.set()触发GPIO输入中断时暂停线程,python,multithreading,events,interrupt,thonny,Python,Multithreading,Events,Interrupt,Thonny,大家好,我正在尝试调用thread类中的一个方法,该方法应该在该线程中设置一个事件标志,导致该线程在设置事件时停止运行。当前代码可以工作,并调用函数,但事件标志似乎不会在线程内部触发 线程负责在按下GUI上的按钮时运行的操作,但如果设置了事件,则不应运行该操作 我的代码的最低版本: import threading import time GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD.UP) global run = 0 class Pump_
import threading
import time
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD.UP)
global run = 0
class Pump_Thread(threading.Thread):
def __init__(self, interval=0.5):
super(Pump_Thread, self).__init__()
self._stop_event = threading.Event()
self.interval = interval
Pump_threads = threading.Thread(target=self.run, daemon=True)
Pump_threads.start()
def stop(self):
self._stop_event.set()
print("Things have stopped yo...")
def resume(self):
self._stop_event.clear()
print("And Now Things will resume")
def run(self)
while not self._stop_event.is_set():
if (run == 1):
#doing some stuff when bit set#
print("Yeah Yeah, I'm running")
class Page1(Page):
def __init__(self, *args, **kwargs):
#Some Initializing methods to load buttons and graphics
self.start_btn=tk.Button(self,height=32,width =80,command=self.Start)
self.start_btn.place(x=50, y=50)
self.reset_btn=tk.Button(self,height=32,width =80,command=self.Reset)
self.reset_btn.place(x=50, y=80)
def Start(self):
global run
run = 1 #<------Set Bit for code to run
def Reset(self):
d = Pump_Thread()
d.resume() #<-----Run Method inside thread
class Monitor_Thread(threading.Thread):
def __init__(self, interval=0.5):
self.interval = interval
Monitor_Threads = threading.Thread(target=self.Monitor_Thread, daemon=True)
Monitor_Threads.start()
def run(self)
while True:
if Condition == True:
d = Pump_Thread()
d.stop() #<-----Run Method inside thread
class Interrupt_Class(page):
def Input(self):
d = Pump_Thread()
d.stop() #<-----Run Method inside thread
GPIO.add_event_detect(18, GPIO.FALLING, callback=Input, bouncetime=300)
class MainView(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, *kwargs)
super().__init__()
p1 = Page1(self) #Other Pages Added here with navigation buttons to raise the page to the front of the GUI#
p1.show()
if __name__ == "__main__":
root = tk.TK()
main = MainView(root)
main.pack(side="top", fill="both", expand=True)
root.wm_geometry("400x400")
root.attributes("-fullscreen", False)
Thread1 = Pump_Thread()
Thread2 = Monitor_Thread()
root.mainloop()
导入线程
导入时间
GPIO.setup(18,GPIO.IN,上下拉=GPIO.PUD.up)
全局运行=0
泵类螺纹(螺纹.螺纹):
定义初始值(自,间隔=0.5):
超级(泵螺纹,自紧)。\uuuuu初始
self.\u stop\u event=threading.event()
self.interval=间隔
Pump_threads=threading.Thread(target=self.run,daemon=True)
泵螺纹。启动()
def停止(自):
self.\u stop\u event.set()
打印(“事情已经停止了…”)
def恢复(自我):
self.\u stop\u event.clear()
打印(“现在一切都将恢复”)
def运行(自我)
而不是自我。停止事件。是否设置()
如果(运行==1):
#在设置位时做一些事情#
打印(“是的,我在跑步”)
班级第1页(第页):
定义初始化(self,*args,**kwargs):
#加载按钮和图形的一些初始化方法
self.start\u btn=tk.按钮(self,高度=32,宽度=80,命令=self.start)
自启动位置(x=50,y=50)
self.reset\u btn=tk.按钮(self,高度=32,宽度=80,命令=self.reset)
自复位位置(x=50,y=80)
def启动(自):
全球运行
运行=1#您正在呼叫:
d = Pump_Thread()
每次调用之前:d.stop()
,这只会使该线程停止
Pump\u Thread
是如何实例化的,您在哪里存储对它的引用
事实上,您没有显示任何类是如何实例化的。您似乎有许多错误堆积在一起
您需要查看有关stackoverflow的许多示例,了解如何创建和管理线程
您可以尝试以下方法:
class Pump_Thread(threading.Thread):
def __init__(self, interval=0.5):
super().__init__()
self._stop_event = threading.Event()
self.interval = interval
def stop(self):
self._stop_event.set()
print("Things have stopped yo...")
def resume(self):
self._stop_event.clear()
print("And Now Things will resume")
def run(self)
while not self._stop_event.is_set():
print("Yeah Yeah, I'm running")
# other parts elided
if __name__ == "__main__":
root = tk.TK()
main = MainView(root)
Thread1 = Pump_Thread()
Thread1.start()
但是现在所有其他需要启动和停止泵送螺纹的位置都需要访问螺纹1
。因此,您应该将其传递到创建的对象中
class Interrupt_Class(page):
def __init__(self, pump):
self.pump = pump
def Input(self):
self.pump.stop() #<-----Run Method inside thread
ic = Interrupt_Class(Thread1)
类中断\u类(第页):
def u u初始(自,泵):
自泵=泵
def输入(自):
self.pump.stop()#好的,现在我可以看到正在实例化的pump_线程
,那么target=self.pump_run
是什么意思?这肯定会产生错误吗?好的,您使用的是target=self.run
,但从线程
派生时,这是隐式的。请看我的另一个答案。对不起,这只是在减少问题代码时的一个输入错误。代码大约有1400行,运行时没有错误或警告,但问题的焦点是新添加的内容,即当从另一个类调用该方法时,为什么事件没有设置为。它不产生错误或警告,并打印消息,但未设置事件。但是,当在类内调用该方法时,事件为setYes,停止
和恢复
方法设置
和清除
线程.event
,但仅适用于所引用的实例。当您调用stop
和clear
时,您应该指的是在调用mainloop()
之前创建的Thread1
实例。很抱歉,我不认为reduce code版本需要它。我对该语言相当陌生,因此犯简单错误或误解新术语对我来说是相当常见的。我承认,对象的使用令人困惑,我希望事件类似于布尔值,您可以通过在类中的任何位置调用该方法在类中设置,它类似于布尔值,但它是每个实例的布尔值。您的run
变量是一个全局变量,它可以在所有实例中工作,但您必须知道,作为一名程序员,您必须非常非常非常努力地避免使用全局变量。事实上,实例变量和类变量之间的混淆已经不止一次地愚弄了我。但是在这种情况下,globals的使用是有益的,因为bit在不同的页面上被监控,以显示它是否为真,并且它只通过用户交互来改变。你能解释一下ic=Interrupt\u Class(Thread1)
的作用吗?我的意思是你正在将引用Thread1
传递到Interrupt\u Class
的一个实例中,这样它就可以self.pump
引用Thread1
的正确实例,然后self.pump.stop()
将按您的意愿执行。