Python如何临时暂停线程?隐写通信工具多线程指令冲突问题求解
问题修复方案
核心问题原因
- Python标准库的
threading.Thread类没有内置pause()方法,也不允许重复调用start(),你原有思路中直接操作线程暂停重启的写法本身就无法执行 - receive线程和write/send线程同时对同一个socket执行
recv()操作,操作系统会把收到的响应数据随机分配给任意一个调用recv()的线程,导致发送流程需要的响应被receive线程拦截吞掉,功能卡住
修复实现
第一步:用事件对象实现receive线程的暂停/恢复
不要直接操作线程对象,改用threading.Event实现线程的阻塞唤醒,对客户端和服务端都做如下修改:
- 类初始化时新增事件对象:
# 客户端__init__里新增 self.receive_enabled = threading.Event() self.receive_enabled.set() # 初始状态允许receive线程运行
- 修改receive方法的循环入口,先判断事件状态:
def receive(self): while self.running: self.receive_enabled.wait() # 事件被clear时会在这里阻塞,相当于暂停 # 原有receive逻辑不变
- 发送方法(客户端write、服务端send)里替换暂停恢复的代码:
# 原来的self.receive_thread.pause()替换为: self.receive_enabled.clear() # 发送完成后原来的self.receive_thread.start()替换为: self.receive_enabled.set()
第二步:修正代码其他语法错误
- 服务端
__init__方法中,启动receive线程前需要先创建线程实例,删掉重复的gui_thread启动代码:
# 服务端__init__里原有错误的self.receive_thread.start()替换为: self.receive_thread = threading.Thread(target=self.receive) self.receive_thread.start() # 删掉重复的gui_thread = threading.Thread(...)启动代码,你已经在最前面启动过了
- 服务端send方法最后发送end指令的代码,修正socket对象引用:
# 原来的self.sock.sendall('end'.encode())替换为: self.socket_client.sendall(b'end')
- 所有socket发送字符串的地方统一转为bytes类型,避免编码异常,比如
self.sock.sendall('send'.encode())可以直接写为self.sock.sendall(b'send')
优化建议
如果要更稳定的实现,建议不要用暂停receive线程的方案,改为所有socket接收操作统一由receive线程处理,收到数据后根据当前状态分发到对应处理逻辑,或者放到队列中供发送流程读取,避免多线程同时读socket的问题。
内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

