Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PyQt4、QThread和在不冻结GUI的情况下打开大文件_Python_Pyqt - Fatal编程技术网

Python PyQt4、QThread和在不冻结GUI的情况下打开大文件

Python PyQt4、QThread和在不冻结GUI的情况下打开大文件,python,pyqt,Python,Pyqt,我想问一下如何从磁盘读取一个大文件,并保持PyQt4 UI的响应性(未被阻止)。我已经将文件的加载移到了QThread子类,但是我的GUI线程被冻结了。有什么建议吗?我想这一定是吉尔的问题,但我不知道如何分类 编辑: 我正在使用GDCM项目中的vtkGDCMImageReader读取多帧DICOM图像,并使用vtk和pyqt4显示它。我在另一个线程(QThread)中执行此加载,但在加载图像之前,我的应用程序将冻结。下面是一个示例代码: class ReadThread(QThread):

我想问一下如何从磁盘读取一个大文件,并保持PyQt4 UI的响应性(未被阻止)。我已经将文件的加载移到了QThread子类,但是我的GUI线程被冻结了。有什么建议吗?我想这一定是吉尔的问题,但我不知道如何分类

编辑: 我正在使用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())

看一看

也许可以在踏板中创建您的读卡器对象:

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())

我猜您正在直接调用
运行
来开始线程。这会使GUI冻结,因为您没有激活线程

因此,您将丢失那里的
开始
,这将间接地正确地调用
运行

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()

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

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

即使您可以进入加载线程,并引入睡眠(0),让GUI继续,这对多核或多处理器机器也没有帮助。发生的情况是O/S有两个线程,并且认为它可以同时运行这两个线程。加载线程设置在(比如)Core1上,GUI可以在(比如)Core2上加载和运行。因此,在启动内核2上的GUI线程的加载和启动之后,O/S将恢复内核1上的加载线程,这将导致promtply获取GIL。片刻之后,GUI线程准备启动,并尝试获取GIL,但失败了。没有GIL它能做的就是回去睡觉


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

你能给我们看一下相关的代码吗?(精简到最低限度。)
QThread
应该可以工作……是的,我一直在读那篇文章,但事实是,当我试图在单独的QThread或threading.Thread中使用vtggdcmimagereader从gdcm读取一个大的dicom多帧图像文件时,我的UI被阻塞,这是一个I/O操作!!!同样的事情,它阻止了我的UIyes,谢谢你的推理,现在唯一成功的办法是在加载程序的内部C++代码中释放吉尔。我知道流水线中有3.2个补丁,每5ms之间会有两个线程翻转。这可能是一个解决方案。不管是Python的time.sleep还是PyQt的QThread.sleep,都有关系吗?@pygabriel抱歉,我现在删除了断开的链接。但是如果你想看的话,你还是可以看的。非常感谢你提供的chached链接!