使用 Event.set() Inside a Thread Class 方法在 GPIO 输入中断触发时暂停线程

Pausing a Thread When GPIO Input Interrupt Triggers using Event.set() Inside a Thread Class Method

大家好,我正在尝试调用线程内的方法 class,该方法应在该线程内设置事件标志,导致线程在设置事件时停止 运行ning .当前代码可以正常工作并调用函数,但事件标志似乎并未在线程内部触发。

当在 GUI 上按下按钮时,线程负责对 运行 的操作,但如果设置了事件,则不应 运行。

我的代码的最小版本:

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()

当中断被触发时,打印“Things have stopped yo...”,因此调用了该方法,但是当按下 GUI 按钮时该过程仍然开始,这意味着事件没有设置。这是什么原因?

您正在呼叫:

d = Pump_Thread()

每次调用之前:d.stop() 这只会使该线程停止。

Pump_Thread 是如何实例化的,您在哪里存储对它的引用?

事实上,您没有显示您的任何 类 是如何实例化的。

你的错误似乎层出不穷。

您需要查看 Whosebug 上有关如何创建和管理线程的许多示例。

您可以尝试这样的操作:

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()

但现在所有其他需要启动和停止的地方 Pump_Thread 都需要访问 Thread1。所以你应该将它传递给创建的对象。

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)