PyQt线程同步问题:如何可靠循环并行执行双线程任务
解决PyQt多线程任务循环重启问题
问题根源
依赖QThreadPool.activeThreadCount()判断线程是否全部结束不可靠,当两个线程几乎同时完成时,线程池的活跃线程计数可能因内部状态更新延迟,导致两次触发progress时计数均为1,错过重启条件。
解决方案
放弃线程池计数,改为手动维护任务完成计数器,直接跟踪两个任务的完成信号。由于PyQt的信号默认在主线程处理,计数器的修改不存在线程安全问题,逻辑更可靠。
修改步骤
- 在类初始化时添加任务完成计数器
- 每次启动新任务时重置计数器
- 在
progress函数中递增计数器,当计数器达到2时(两个任务均完成),触发新一轮任务
完整代码示例
from PyQt5.QtCore import QRunnable, pyqtSignal, QObject, QThreadPool import time class WorkerSignals(QObject): finished = pyqtSignal() class Worker1(QRunnable): def __init__(self, parent): super().__init__() self.parent = parent self.signals = WorkerSignals() def run(self): self.parent.get_data_1() self.signals.finished.emit() class Worker2(QRunnable): def __init__(self, parent): super().__init__() self.parent = parent self.signals = WorkerSignals() def run(self): self.parent.get_data_2() self.signals.finished.emit() class MainWindow: def __init__(self): self.threadpool = QThreadPool.globalInstance() self.stop_button_pressed = False self.index_1 = 0 self.index_2 = 0 self.completed_tasks = 0 # 任务完成计数器 def get_data_1(self): self.index_1 += 1 time.sleep(0.1) return self.index_1 def get_data_2(self): self.index_2 += 1 time.sleep(0.1) return self.index_2 def start(self): self.stop_button_pressed = False self.completed_tasks = 0 # 启动新任务前重置计数器 self.worker1 = Worker1(self) self.worker2 = Worker2(self) self.worker1.signals.finished.connect(self.progress) self.worker2.signals.finished.connect(self.progress) self.threadpool.start(self.worker1) self.threadpool.start(self.worker2) def progress(self): if self.stop_button_pressed: print('stop button pressed') return self.completed_tasks += 1 print(f'completed tasks: {self.completed_tasks}, indices: {self.index_1}, {self.index_2}') # 两个任务均完成时启动新一轮 if self.completed_tasks == 2: self.start() def stop(self): self.stop_button_pressed = True
说明
- 计数器直接绑定任务完成信号,不受线程池内部状态更新延迟影响,确保只有两个任务都完成后才会重启
- 所有信号处理逻辑在主线程执行,无需额外加锁,避免线程安全问题
内容的提问来源于stack exchange,提问作者Huapua
相关产品推荐
相关产品推荐

