PyQt4,QThread和打开大文件而不冻结GUI

时间:2009-11-20 22:51:02

标签: python pyqt

我想问一下如何从磁盘读取一个大文件并保持PyQt4 UI响应(未阻止)。我已经将文件的负载移动到QThread子类,但我的GUI线程被冻结了。有什么建议?我认为它必须与GIL有关,但我不知道如何对它进行排序?

编辑: 我正在使用GDCM项目中的vtkGDCMImageReader来读取多帧DICOM图像并使用vtk和pyqt4显示它。我在另一个线程(QThread)中加载,但我的应用程序冻结,直到图像加载。这是一个示例代码:

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
        self.reader.vtkgdcm.vtkGDCMImageReader()

    def run(self): 
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())

4 个答案:

答案 0 :(得分:3)

我猜你正在直接调用run来开始这个帖子。这会使GUI冻结,因为你没有激活线程。

所以你错过了那里的start,这会间接地正确地调用run

thread = ReadThread()
thread.begin()

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
        self.reader.vtkgdcm.vtkGDCMImageReader()

    def run(self): 
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())

    def begin(self): 
        self.start()

答案 1 :(得分:2)

有点晚了,但我想我可以找出你面临的问题。

图像很大,解压缩可能是CPU密集型任务。这意味着您的GUI线程进入休眠状态,加载线程受CPU限制。此时加载线程具有GIL,GUI无法启动。

即使您可以进入加载线程并引入睡眠(0),以使GUI继续运行,这对于多核处理器或多处理器机器也无济于事。发生的事情是O / S有两个线程,并认为它可以同时运行。加载线程设置在(例如)核心1上,GUI可以加载并运行(例如)核心2.因此,在核心2上启动加载并启动GUI线程后,O / S恢复加载线程在核心1 - 它突然抓住了GIL。片刻之后,GUI线程就可以开始了,并尝试获取失败的GIL。没有GIL它可以做的就是回去睡觉!

一种解决方案是以策略间隔在后台线程中插入一个短(大于零)睡眠,以便GUI可以运行。这并不总是可行的。

答案 2 :(得分:1)

答案 3 :(得分:0)

也许在步骤中创建您的读者对象:

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
-       self.reader = vtkgdcm.vtkGDCMImageReader()

    def run(self): 
+       self.reader = vtkgdcm.vtkGDCMImageReader()
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())