python - 使用python控制线程中的循环

标签 python multithreading

我有一个线程类,我想在我的主函数中多次启动/停止我的线程。我用了this linkthis method解决我的问题。这是一个简单的线程,它在控制台中打印击键:

global isWindows

isWindows = False


try:
    from win32api import STD_INPUT_HANDLE
    from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT
    import win32gui
    import threading
    from time import sleep
    import sys
    isWindows = True
except ImportError as e:
    import sys
    import select
    import termios


class KeyPoller(threading.Thread):

    def __init__(self):
        super(KeyPoller, self).__init__()
        #threading.Thread.__init__(self)
        self.stop_event = threading.Event()
        global isWindows
        if isWindows:
            self.readHandle = GetStdHandle(STD_INPUT_HANDLE)
            self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)

            self.curEventLength = 0
            self.curKeysLength = 0

            self.capturedChars = []
        else:
            # Save the terminal settings
            self.fd = sys.stdin.fileno()
            self.new_term = termios.tcgetattr(self.fd)
            self.old_term = termios.tcgetattr(self.fd)

            # New terminal setting unbuffered
            self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO)
            termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)

    def poll(self):
        if isWindows:
            if not len(self.capturedChars) == 0:
                return self.capturedChars.pop(0)

            eventsPeek = self.readHandle.PeekConsoleInput(10000)

            if len(eventsPeek) == 0:
                return None

            if not len(eventsPeek) == self.curEventLength:
                for curEvent in eventsPeek[self.curEventLength:]:
                    if curEvent.EventType == KEY_EVENT:
                        if ord(curEvent.Char) == 0 or not curEvent.KeyDown:
                            pass
                        else:
                            curChar = str(curEvent.Char)
                            self.capturedChars.append(curChar)
                self.curEventLength = len(eventsPeek)

            if not len(self.capturedChars) == 0:
                return self.capturedChars.pop(0)
            else:
                return None
        else:
            dr,dw,de = select.select([sys.stdin], [], [], 0)
            if not dr == []:
                return sys.stdin.read(1)
            return None

    def stop(self):
        print("stopping the thread")
        self.stop_event.set()

    def stopped(self):
        return self.stop_event.is_set()

    def run(self):
        while not self.stopped():
            c=self.poll()
            if not c is None:
                print(c)

if __name__=='__main__':

    thr=KeyPoller()
    print("starting the thread #1")
    thr.start()
    sleep(5)
    print("stopping the thread #1")
    # sadly if you press any key in this time it would be saved and printed after  thr2.start
    thr.stop()
    thr.join()
    sleep(5)
    thr2=KeyPoller()
    print("starting the thread #2")
    thr2.start()
    sleep(5)
    print("stopping the thread #2")
    thr2.stop()
    print("Exiting the whole program")

我的问题是当我调用 thr.stop() 并尝试按下一些键时它退出 while 循环并且线程似乎已经停止但是当我调用 thr2. start() 它从我的线程的第一个实例打印旧的击键,似乎所有击键仍然存在,无论我是否调用停止函数。

最佳答案

从我的角度来看,我不认为将 treading.event() 初始化为实例变量有什么意义。事件用于线程/进程同步,如果您在一个实例中声明它,则其他实例将看不到它。

话虽如此,根据您的代码,我会为 stop_event 使用 bool 变量。这在 Linux 环境中对我有用。

class KeyPoller(threading.Thread):

    def __init__(self):
        super(KeyPoller, self).__init__()
        #threading.Thread.__init__(self)
        self.stop_event = False
        global isWindows
        if isWindows:
            self.readHandle = GetStdHandle(STD_INPUT_HANDLE)
            self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)

            self.curEventLength = 0
            self.curKeysLength = 0

            self.capturedChars = []
        else:
            # Save the terminal settings
            self.fd = sys.stdin.fileno()
            self.new_term = termios.tcgetattr(self.fd)
            self.old_term = termios.tcgetattr(self.fd)

            # New terminal setting unbuffered
            self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO)
            termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)

    def poll(self):
        if isWindows:
            if not len(self.capturedChars) == 0:
                return self.capturedChars.pop(0)

            eventsPeek = self.readHandle.PeekConsoleInput(10000)

            if len(eventsPeek) == 0:
                return None

            if not len(eventsPeek) == self.curEventLength:
                for curEvent in eventsPeek[self.curEventLength:]:
                    if curEvent.EventType == KEY_EVENT:
                        if ord(curEvent.Char) == 0 or not curEvent.KeyDown:
                            pass
                        else:
                            curChar = str(curEvent.Char)
                            self.capturedChars.append(curChar)
                self.curEventLength = len(eventsPeek)

            if not len(self.capturedChars) == 0:
                return self.capturedChars.pop(0)
            else:
                return None
        else:
            dr,dw,de = select.select([sys.stdin], [], [], 0)
            if not dr == []:
                return sys.stdin.read(1)
            return None

    def stop(self):
        print("stopping the thread")
        self.stop_event = True

    def stopped(self):
        return self.stop_event

    def run(self):
        while not self.stopped():
            c=self.poll()
            if not c is None:
                print(c)

关于python - 使用python控制线程中的循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45647820/

相关文章:

python - 使用 python 绘制曲线而不是条形图

android - 在新线程中从服务注册广播接收器

asp.net - SQL Server,连接池与特殊情况下的静态连接

windows - WaitForSingleObject 是否放弃线程的时间片?

android - 为什么线程不停止?

python - 将 SWIG 应用于 C++ 时,f1(const char* str) 与 f1(char* str) 是否不同?

python - 如何使用 httpretty/sure 执行 python 测试

python - 使用 pytables,哪个更有效 : scipy. 稀疏矩阵或 numpy 密集矩阵?

python - 为什么在 Python 目录中创建 postscript 文件?

java - 使用多个服务或在单个服务中执行所有操作哪个更好?