首页 > 解决方案 > 停止执行 python 线程并启动一个新线程

问题描述

我目前正在研究 Python 中的一些设计模式,并尝试实现图中的状态模式示例:

电梯门状态图

[编辑:@jaykip 发现了原始问题。我在打开/关闭对象实例化中传递了 wrng 对象,现在我只想用按钮取消打开/关闭过程]

它碰巧比我预期的要复杂得多,我为四种状态和方法中的每一种都创建了一个openclose。为了模拟打开和关闭按钮,我使用了 thpynput模块,这样我就可以听键盘并调用openclose按钮,为了模拟打开和关闭的门传感器,我只需调用一个sleep函数等待 3 秒,直到门关闭/打开。

它工作正常,直到我决定使用线程,所以sleep函数调用不会阻塞主程序,我可以在门关闭/打开时“按下按钮”。现在状态并没有像它应该的那样改变。继承人的代码和一个运行的例子:

from time import sleep
from pynput import keyboard
from threading import Thread


class Open():
    def __init__(self, door):
        self.door = door
        print('Open')

    def open(self):
        pass

    def close(self):
        self.door.state = Closing(self.door)
        for _ in range(3):
            print('.', end='', flush=True)
            sleep(1)
        self.door.state = Closed(self.door)


class Opening():
    def __init__(self, door):
        self.door = door
        print('Opening', end='')

    def open(self):
        pass

    def close(self):
        self.door.state = Closing(self.door)
        for _ in range(3):
            print('.', end='', flush=True)
            sleep(1)
        self.door.state = Closed(self.door)


class Closed():
    def __init__(self, door):
        self.door = door
        print('Closed')

    def close(self):
        pass

    def open(self):
        self.door.state = Opening(self.door)
        for _ in range(3):
            print('.', end='', flush=True)
            sleep(1)
        self.door.state = Open(self.door)


class Closing():
    def __init__(self, door):
        self.door = door
        print('Closing', end='')

    def close(self):
        pass

    def open(self):

        self.door.state = Opening(self.door)
        for _ in range(3):
            if type(self.door.state) == Opening:
                print('.', end='', flush=True)
                sleep(1)
        self.door.state = Open(self.door)


class ElevatorDoor:
    def __init__(self):
        self.state = Open(self)

    def open(self):
        Thread(target=self.state.open).start()

    def close(self):
        Thread(target=self.state.close).start()


if __name__ == '__main__':
    door = ElevatorDoor()

    def on_press(key):
        global door
        if key == keyboard.Key.esc:
            return False  # stop listener
        try:
            k = key.char  # single-char keys
        except Exception:
            k = key.name  # other keys

        if k == 'o':
            door.open()
        if k == 'c':
            door.close()

    listener = keyboard.Listener(on_press=on_press)
    listener.start()
    listener.join()

这就是发生的事情:

<initial state is Open>
Open
<press 'c' key>
Closing...Closed
<wait it finishes and press 'o' key>
Opening...Open
<press 'c' key and while closing press 'o' key>
Closing..Opening...Closed
Open

关于如何取消前一个关闭线程的任何想法,以便它不会将状态更改为 Clodes 并在打开过程的中间打印“已关闭”?

标签: pythondesign-patternspython-multithreading

解决方案


看起来您正在传递Open, etc. 对象作为下一个状态对象的参数。在close函数中,它设置self.door.state = Closed(self),对象在self哪里OpenClosed正在寻找工作的ElevatorDoor对象。改为尝试self.door:) 我找不到 pynput 模块,所以我无法测试它,但我希望这会有所帮助。


推荐阅读