You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt线程同步问题:如何可靠循环并行执行双线程任务

解决PyQt多线程任务循环重启问题

问题根源

依赖QThreadPool.activeThreadCount()判断线程是否全部结束不可靠,当两个线程几乎同时完成时,线程池的活跃线程计数可能因内部状态更新延迟,导致两次触发progress时计数均为1,错过重启条件。

解决方案

放弃线程池计数,改为手动维护任务完成计数器,直接跟踪两个任务的完成信号。由于PyQt的信号默认在主线程处理,计数器的修改不存在线程安全问题,逻辑更可靠。

修改步骤

  1. 在类初始化时添加任务完成计数器
  2. 每次启动新任务时重置计数器
  3. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:42:38