Python客户端-服务器问答游戏输入监听线程无法终止问题
问题分析
你的核心问题在于输入监听线程__input_listener是死循环,且input()是阻塞调用——即使外部把is_playing设为False,线程仍会卡在input()等待用户输入,无法响应终止信号,导致主线程的listener_thread.join()一直阻塞。
解决方案
给监听线程添加终止事件(threading.Event),同时用非阻塞方式监听输入,让线程能定期检查终止信号,具体修改如下:
修改监听线程函数
引入select模块实现带超时的输入监听,同时接收终止事件作为参数:
def __input_listener(self, input_queue, stop_event): import sys import select while not stop_event.is_set(): # 每隔0.5秒检查一次stdin是否有输入,同时响应终止信号 ready, _, _ = select.select([sys.stdin], [], [], 0.5) if ready: try: # 模拟input()的行为,读取一行并去掉末尾换行 message = sys.stdin.readline().strip() if message: input_queue.put(message) except EOFError: break
修改输入处理函数
创建终止事件并传给监听线程,在需要终止时触发事件:
def __handle_user_inputs(self): import threading input_queue = queue.Queue() stop_event = threading.Event() listener_thread = threading.Thread(target=self.__input_listener, args=(input_queue, stop_event)) listener_thread.start() while self.is_alive and self.is_playing: try: message = input_queue.get(timeout=0.5) self.__send_message(message) except queue.Empty: if not self.is_playing: break # 通知监听线程终止 stop_event.set() listener_thread.join() # 线程会快速退出,不再阻塞
关键说明
- 终止事件(Event):作为线程间的安全通信机制,用来通知监听线程需要退出。
- 带超时的输入监听:用
select.select()替代阻塞的input(),每隔0.5秒检查一次输入和终止信号,避免线程一直卡在等待输入的状态。 - 行为一致性:
sys.stdin.readline().strip()和input()的行为一致,都会读取用户输入的一行并去掉末尾的换行符。
内容的提问来源于stack exchange,提问作者Gil Ari Agmon
相关产品推荐
相关产品推荐

