首页 > 解决方案 > 如何使用 ThreadPool 通知主线程进行并行计算(PyQt)

问题描述

我有一个 for 循环来读取大量图像,并且我想使用多线程进行加速。我可以从 Internet 上找到很多关于 QThread 的示例。但是,其中许多示例并不是为加速而设计的。

最后,我找到了一个使用多线程方法加速for循环的例子。代码是:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import multiprocessing
from multiprocessing.pool import ThreadPool
from multiprocessing.dummy import Pool as DummyPool
from multiprocessing import Pool as ProcessPool
import time


class MainWindow(QMainWindow):
    finished = pyqtSignal()
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("QDicomLabel Test")
        self.resize(500, 500)

        widget = QWidget()
        self.setCentralWidget(widget)

        layout = QHBoxLayout()
        widget.setLayout(layout)

        btn = QPushButton('run')
        layout.addWidget(btn)

        label = QLabel('0')
        layout.addWidget(label)
        self.label = label
        btn.clicked.connect(self.run)

        self.num = 0

        self.finished.connect(self.updateText)

    def run(self):

        num = 4
        p = ThreadPool(num)
        start_time = time.time()
        ret = p.map(self.readfile, range(200))
        p.close()
        p.join()
        print("thread_pool  %d, costTime: %fs ret.size: %d" % (num, (time.time() - start_time), len(ret)))

    def readfile(self, name):
        time.sleep(0.01)
        # self.signal.finished.emit()

    def updateText(self):
        self.num = self.num + 1
        self.label.setText(str(self.num))
        # QCoreApplication.processEvents()

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

在上面的代码中,我需要读取 200 张图片,我假设读取每个文件需要 0.01s。所以,我们需要大约 2s 来读取所有文件。

在运行函数中,变量“num”影响速度。如果num = 4,读取所有文件大约需要0.5s。当然,它加快了我的阅读速度。

然后,我需要在 GUI 中更新进度。在我的想法中,我将在函数“readfile”中发出一个信号,函数“updateText”将接收信号,然后在 GUI 中更新进度。发出的信号已在函数“readfile”中注释(self.signal.finished.emit()),因为它会破坏 GUI。

那么,如何在 GUI 中更新进度呢?

标签: multithreadingparallel-processingpyqt

解决方案


试试看:

def readfile(self, name):
    #time.sleep(0.01)
    QThread.msleep(10)
    # self.signal.finished.emit()
    self.finished.emit()

推荐阅读