numpy 在执行CPU密集型任务时,如何保持pyqt GUI的响应速度?

t3psigkw  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(92)

我正在编写一个数据采集程序,我对保持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挂起的原因吗?或者像我这样共享变量有问题吗?对于这种情况有什么解决方法吗?

ngynwnxp

ngynwnxp1#

您可以使用multiprocessing.ProcessPool进程在单独的进程中运行任务。由于Python中的进程没有GIL,因此它们可以独立于主进程(GUI)执行CPU任务,然后通过Pipes或multiprocessing.Queue子进程发送可以在GUI(主进程)中显示的数据。

cnjp1d6j

cnjp1d6j2#

你可以使用线程来解决你的问题。
你可以把你的图像写入函数放在一个新的线程中,然后这个任务将独立于你的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()

相关问题