PyQT5 多线程问题
Posted
技术标签:
【中文标题】PyQT5 多线程问题【英文标题】:PyQT5 Multi Thread Issue 【发布时间】:2021-03-28 08:36:14 【问题描述】:我正在尝试使用 PYQT5 和 Qthread 运行多线程
我有两个与线程关联的按钮(进度条和一个操作等待 1 秒,然后打印“完成”),它们在同一个类中声明时运行良好。
我确实有第三个按钮,我链接到另一个类中插入的操作。这使我的程序在没有任何日志消息的情况下崩溃。真正让程序崩溃的是“self.thread2.start()”这行代码。
我不明白为什么这不起作用!你能帮我理解这个问题吗?
提前致谢
import sys
from PyQt5.QtCore import *
from thread_progressbar import *
from Test_MT import *
class SimulationUi(QtWidgets.QDialog):
def __init__(self):
super(SimulationUi, self).__init__()
self.btnStart = QtWidgets.QPushButton('Start')
self.btnStart2 = QtWidgets.QPushButton('Start')
self.btnStop = QtWidgets.QPushButton('Stop')
self.btnStop2 = QtWidgets.QPushButton('Stop')
self.btnQuit = QtWidgets.QPushButton('Quit')
self.myprogressbar = QtWidgets.QProgressBar()
self.myprogressbar2 = QtWidgets.QProgressBar()
self.grid = QtWidgets.QGridLayout()
self.grid.setSpacing(10)
self.grid.addWidget(self.btnStart,1,0)
self.grid.addWidget(self.btnStop,1,1)
self.grid.addWidget(self.myprogressbar,2,0,1,3)
self.grid.addWidget(self.btnStart2, 3, 0)
self.grid.addWidget(self.btnStop2, 3, 1)
self.setLayout(self.grid)
# ------------------------
#MULTI-THREAD MANAGEMENT
#------------------------
self.thread = QThread()
self.thread.start()
self.worker = thread_progressbar()
self.worker.moveToThread(self.thread)
self.worker.setValue.connect(self.myprogressbar.setValue)
self.btnStart.clicked.connect(self.worker.startpgbar)
self.btnStop.clicked.connect(lambda: self.worker.stoppgbar())
class_tst = MakeList()
class_tst.define_thread(self.btnStart2)
self.thread3 = QThread()
self.thread3.start()
self.worker3 = Test()
self.worker3.moveToThread( self.thread3 )
self.btnStop2.clicked.connect( self.worker3.MT )
def stop_thread(self):
self.worker.stop()
self.thread.quit()
self.thread.wait()
def quit_application(self):
self.close()
class MakeList():
def __init__(self):
super(MakeList, self).__init__()
def define_thread(self, MyObject):
self.thread2 = QThread()
self.thread2.start()
self.worker2 = Test()
self.worker2.moveToThread(self.thread2 )
MyObject.clicked.connect( self.worker2.MT )
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
simul = SimulationUi()
simul.show()
sys.exit(app.exec_())
Test_MT 文件
import os, time
from PyQt5 import QtCore
class Test(QtCore.QObject):
def MT(self):
time.sleep(1)
print("done")
【问题讨论】:
很难真正区分,因为您的代码缺少某些部分(例如,thread_progressbar
在哪里?)并且通常有点混乱(您将对象移动到已经开始,你的命名并不是很冗长和一致)。也就是说,没有minimal, reproducible example,我们只能猜测。我的猜测是Makelist
是一个局部变量并且超出了范围,这会导致由于线程在运行时被破坏而导致崩溃。但是,如前所述,这只是一个猜测。提供 MRE。
【参考方案1】:
由于在SimulationUi.__init__
中对MakeList
实例的唯一引用是局部变量class_tst
,因此当SimulationUi.__init__
返回时,该对象及其属性将被垃圾回收。由于其属性之一是正在运行的线程 (class_tst.thread2
),这会导致程序崩溃。解决这个问题的最简单方法是通过将MakeList
对象分配给SimulationUi
的实例变量而不是局部变量(即在SimulationUi.__init__
中使用self.class_tst = MakeList()
而不是class_tst=MakeList()
)来持久引用MakeList
。
【讨论】:
你在现场!这对我理解它的整体工作方式有很大帮助!以上是关于PyQT5 多线程问题的主要内容,如果未能解决你的问题,请参考以下文章
PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题
PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题
PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题