针对PyQT5和PySide6,在启动线程后,如果退出主线程,总是出现:QThread: Destroyed while thread is still running,这个提示意味着,在主线程退出后,程序中创建的子线程还在运行中,即无法彻底终止子线程。
目前网上有n多解决方案,但实际没有讲到点子上。我这里总结经验如下:退出时,必须停止创先子线程;!
1、主线程要显式调用子线程的析构函数__del__(),
2、线程的析构函数中,通过标志位方式,停止程序运行,即正常结束即可。
主程序中的,显示调用析构函数:
@Slot()
def btn_close_clicked(self):
self.thread.__del__()
self.close()
在线程的析构函数中,设置标志位来控制任务循环体
QTheard的析构函数:
def __del__(self):
print('Stop thread task running.')
self.status = False
self.wait()
QT heard的任务函数:
def run(self):
print('Start a new thread task.')
while self.status:
self.count += 1
self.s = f"已执行{self.count}秒"
self.sig.emit(self.s)
time.sleep(1)
经测试后,点击“EXIT"按钮,正常调用析构函数后,不在提示。
但是,如果点击右上角”X“按钮,由于不能正常显式调用析构函数,依然还是有提示的。切记切记!
最后,验证的全部代码如下,供各位学习借鉴。
'''
@File : ex_Thread.py
@Time : 2022/12/01 15:08:13
@Author :
@Version : 1.00.000
@Contact :
@License : (C)Copyright 2022, Info Analysis and Insight for Future Studios
@https : None
@Desc : None
'''
# here put the import lib
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import time
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.initUi()
self.conn()
self.show()
# init self
def initUi(self):
self.setWindowTitle('QThread example')
self.resize(300, 200)
layout = QVBoxLayout()
self.label = QLabel('labeltext')
self.btn = QPushButton('OK')
self.btn_close =QPushButton('EXIT')
# self.setCentralWidget(self.label)
layout.addWidget(self.label, 0, Qt.AlignCenter)
layout.addWidget(self.btn)
layout.addWidget(self.btn_close)
self.setLayout(layout)
self.thread = Worker()
def conn(self):
self.thread.sig.connect(self.updateLabel)
self.btn.clicked.connect(self.buttonClicked)
self.btn_close.clicked.connect(self.btn_close_clicked)
@Slot()
def buttonClicked(self):
self.thread.start()
@Slot()
def updateLabel(self, text):
self.label.setText(text)
@Slot()
def btn_close_clicked(self):
self.thread.__del__()
self.close()
class Worker(QThread):
sig = Signal(str)
def __init__(self, parent=None):
print('Created a new thread of Worker')
super(Worker, self).__init__(parent)
self.status = True
self.count = 0
def __del__(self):
print('Stop thread task running.')
self.status = False
self.wait()
def run(self):
print('Start a new thread task.')
while self.status:
self.count += 1
self.s = f"已执行{self.count}秒"
self.sig.emit(self.s)
time.sleep(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
app.exec()