循环函数,直到调用另一个函数

时间:2016-03-08 11:46:59

标签: python raspberry-pi2 python-multithreading

我正在制作一个在 Raspberry Pi 支持的LCD屏幕上运行的菜单。我正在尝试使用线程模块使LCD上的文本更新,直到菜单位置发生变化。

菜单由菜单位置更改时调用的函数列表组成。使用事件处理程序从类外部调用switch_menu()函数,并用于调用正确的菜单函数。其中一些功能(item2);我希望他们循环,并与其他人(item1);只显示静态文本。重要的是,当再次调用switch_menu()时,它们会停止循环。我怎么能这样做?

(这是我的代码的简化版本)

class Menu:
    def __init__(self):
        self.LCD = Adafruit_CharLCD()

        self.m_pos = 0      

        self.items = [self.item1,self.item2]

        self.switch_menu(0)

    def switch_menu(self,operation):   
        # 2. And here I want to stop it.   
        m_pos = self.m_pos

        pos = m_pos
        max_pos = len(self.items) - 1
        m_pos = self.loop_selection(pos,max_pos,operation)

        # 1. Here I want to start looping the function below.
        self.items[m_pos]()

        self.m_pos = m_pos

    def loop_selection(self,pos,max_pos,operation):
        if pos >= max_pos and operation == 1:
            pos = 0
        elif pos <= 0 and operation == -1:
            pos = max_pos
        else:
            pos += operation
        return pos

    def item1(self):
        self.LCD.clear()
        text = "item1"
        self.LCD.message(text)

    def item2(self):
        while True:
            self.LCD.clear()
            text = "item2"
            self.LCD.message(text)
            time.sleep(10)

2 个答案:

答案 0 :(得分:0)

有很多方法可以实现这一点,一种简单的方法是在变量中进行 while 循环,然后在循环外部将其设置为 False (例如,一旦你想要停止它,当调用switch_menu时。请注意可能引起的任何竞争条件,由于我不了解您的其余代码,因此我无法进行更多的讨论。

答案 1 :(得分:0)

典型的,我一直试图让这个工作几天,并且我发布一个问题;我找到了答案。

这是我找到答案的地方: Stopping a thread after a certain amount of time

这就是我做的工作:

class Menu:
    def __init__(self):
        self.LCD = Adafruit_CharLCD()

        self.m_pos = 0      

        self.items = [self.item1,self.item2]

        self.switch_menu(0)

    def switch_menu(self,operation):  
        try:
            self.t_stop.set()
        except:
            pass 

        m_pos = self.m_pos

        pos = m_pos
        max_pos = len(self.items) - 1
        m_pos = self.loop_selection(pos,max_pos,operation)

        item = self.items[m_pos][0]
        self.t_stop = threading.Event()
        self.t = threading.Thread(target=item,args=(1,self.t_stop))
        self.t.start()

        self.m_pos = m_pos

    def loop_selection(self,pos,max_pos,operation):
        if pos >= max_pos and operation == 1:
            pos = 0
        elif pos <= 0 and operation == -1:
            pos = max_pos
        else:
            pos += operation
        return pos

     def item1(self,arg):
        while not stop_event.is_set():
            text = "item1"
            self.LCD.clear() 
            if not stop_event.is_set(): self.LCD.message(text)
            stop_event.wait(10)

    def item2(self,arg):
        while not stop_event.is_set():
            text = "item2"
            self.LCD.clear()
            if not stop_event.is_set(): self.LCD.message(text)
            stop_event.wait(10)

我使用了try / except来绕过switch_menu()的初始执行:

try:
    self.t_stop.set()
except:
    pass

我第二次检查条件作为解决方法,以防止竞争条件:

if not stop_event.is_set(): self.LCD.message(text)

我不知道为什么在创建线程时我必须传递一个参数,但是当我没有时它会给我错误:

self.t = threading.Thread(target=item,args=(1,self.t_stop))

我知道它需要一些整理,但它确实有效。如果有人有一个更优雅的解决方案随时发布它。