PyQt5如何通过点击停止按钮主动终止运行中的QThread串口读取线程
实现方案
核心原则:不要直接调用QThread.terminate()强制杀线程,这种方式会跳过资源清理逻辑,可能导致串口未正常释放、内存泄漏等问题,推荐用标志位+主动退出的安全终止方案。
第一步:修改Worker类,添加停止控制逻辑
给Worker加运行状态标志位、停止方法,同时调整Reader的读取逻辑,增加退出检查。
class Worker(QObject): finished = pyqtSignal() progress = pyqtSignal(list) def __init__(self): QObject.__init__(self) self._is_running = True # 新增运行状态标志 self._Reader = Reader() self._Reader.progress = self.progress self._Reader.finished = self.finished self._Reader.worker = self # 把worker实例传给Reader,方便读取标志位 # 新增停止方法,外部调用修改标志位 def stop(self): self._is_running = False def run(self): self._Reader.read()
注意:如果你的
Reader.read()内部是循环读取串口的逻辑,需要在每次循环中检查停止标志,同时给串口设置读取超时,避免阻塞在读取操作上无法检查标志。以pyserial为例修改read方法:
# Reader类的read方法修改示例 class Reader: def read(self): # 给串口设置读取超时,比如0.5秒,超时后read会返回空,不会一直阻塞 self.serial.port.timeout = 0.5 # 循环判断运行标志位,标志位被修改后自动退出循环 while self.worker._is_running: data = self.serial.read(1024) # 读取串口数据 if data: # 处理数据、触发progress信号 processed_data = your_process_logic(data) self.progress.emit(processed_data) # 退出循环后清理串口、触发finished信号 self.serial.close() self.finished.emit()
第二步:实现stopClicked槽函数
直接调用worker的stop方法修改标志位,等待线程自行退出即可:
def stopClicked(self): if hasattr(self, 'worker') and self.thread.isRunning(): self.worker.stop() # 可选:等待线程完全退出,避免后续操作冲突 self.thread.wait()
注意事项
- 如果你的串口读取逻辑不允许设置超时,可以用
serial.in_waiting先判断有没有可读数据,没有的话就休眠100ms再检查标志位,避免空转占满CPU - 停止后如果需要再次启动,直接调用原来的
startClicked逻辑即可,不需要额外调整
内容的提问来源于stack exchange,提问作者Benedikt Bergenthal
相关产品推荐
相关产品推荐

