在执行 CPU 密集型任务时如何保持 pyqt GUI 的响应能力?

问题描述 投票:0回答:2

我正在编写一个数据采集程序,我有兴趣保持 GUI 始终响应。这就是为什么我使用 QThreads 来完成这项工作。尽管与整个工作在单个线程中完成的情况相比,结果稍好一些,但我的 GUI 仍然挂起,直到任务完成。这是代码的相关部分:

import numpy as np
from PyQt4 import QtGui, QtCore
import h5py as hdf
import tifffile as tiff


class MyWidget(QtGui.QFrame):

    def __init__(self, *args, **kwargs):

        super(MyWidget, self).__init__(*args, **kwargs)
        self.convertButton = QtGui.QPushButton('Convert to TIFF')
        self.convertButton.clicked.connect(self.convertToTiff)
        recGrid = QtGui.QGridLayout()
        self.setLayout(recGrid)
        recGrid.addWidget(self.convertButton, 0, 0)

    def convertToTiff(self):
        self.converterThread = QtCore.QThread()
        self.converter = TiffConverter(self.savename, self.dataname)
        self.converter.moveToThread(self.converterThread)
        self.converterThread.started.connect(self.converter.run)
        self.converterThread.start()


class TiffConverter(QtCore.QObject):

    def __init__(self, filename, dataname, *args, **kwargs):
        super(TiffConverter, self).__init__(*args, **kwargs)
        self.filename = filename
        self.dataname = dataname
        self.file = hdf.File(self.filename, mode='r')

    def run(self):
        tiff.imsave(self.filename, self.file[self.dataname])
        self.file.close()


if __name__ == '__main__':
    app = QtGui.QApplication([])

    win = MyWidget()
    win.show()

    app.exec_()

我知道 GUI 挂在

tiff.imsave(self.filename, self.file[self.dataname])
并且我熟悉 QThreads 并没有真正进行并行计算这一事实。这可能是 GUI 挂起的原因吗?或者像我一样共享变量有问题吗?对于此类情况有什么解决办法吗?

python numpy pyqt
2个回答
0
投票

您可以使用进程的

multiprocessing.Process
Pool
在单独的进程中运行任务。由于Python中的进程没有GIL,它们可以与主进程(GUI)分开执行CPU任务,然后通过管道或
multiprocessing.Queue
子进程发送可以在GUI(主进程)中显示的数据。


-1
投票
您可以使用线程来解决您的问题。

您可以将图像写入功能放在一个新线程中,然后该任务将独立于您的 UI 部分,因此不会滞后。

我已经完成了,如果您需要任何进一步的帮助,请告诉我。

class ThreadLiveViewProcessing(QThread): def __init__(self): super(ThreadLiveViewProcessing, self).__init__() self.is_ThreadLiveViewProcessing_running = True def run(self): enter code here
然后你可以在 UI 类的 init 中创建它的实例。

class MyWidget(QtGui.QFrame): def __init__(self, *args, **kwargs): super(MyWidget, self).__init__(*args, **kwargs) # Thread should never have parents. # Create instance of Thread Class for processing in faceme. self.thread_live_view_processing = ThreadLiveViewProcessing() self.thread_live_view_processing.start() ... snippet ... code ... etc. recGrid = QtGui.QGridLayout() self.setLayout(recGrid) recGrid.addWidget(self.convertButton, 0, 0)
您可以在需要的地方启动线程:

self.thread_live_view_processing.start()
    
© www.soinside.com 2019 - 2024. All rights reserved.