我有一个线程类,我想在我的主函数中多次启动/停止我的线程。我用了this link与 this 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/