我想在我的应用程序中有 2 个工作线程。一个应该在 GUI 加载后立即开始运行,另一个应该稍后通过某个信号启动。假设这是一次按钮点击。
当我的 Python 解释器在执行第二个线程时崩溃(如显示 Windows 错误“Python 停止工作”,没有堆栈跟踪)时,我遇到了奇怪的行为。
这是一个示例,单击按钮后就会崩溃。
class Worker(QtCore.QThread):
def __init__(self, method_to_run):
super().__init__()
self.method = method_to_run
def run(self):
self.method()
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QPushButton('Test', self)
self.label = QLabel(self)
self.button.clicked.connect(self.handleButton)
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.button)
self.worker = Worker(self.test_method)
self.worker.start()
def handleButton(self):
self.label.setText('Button Clicked!')
worker = Worker(self.test_method)
worker.start()
@staticmethod
def test_method():
res = [i*i for i in range(100500)]
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
更奇怪的是,当您出于某种原因调试应用程序时,它不会崩溃。
我在这里缺少什么?
编辑 我可以从故障转储中获得很多信息,因为我没有 QT 的符号。但看起来崩溃发生在 QtCore.dll 内部
ExceptionAddress: 00000000632d4669 (Qt5Core!QThread::start+0x0000000000000229)
最佳答案
问题是您没有保存对线程的引用,因此一旦退出handleButton
,它就会被删除。如果您保存引用,这就引出了如何处理其生命周期的问题。
QThread
不仅仅是系统线程的包装器 - 它还实现了其他服务,使您可以将线程连接到 GUI 中。您可以使用其 finished
处理程序在小部件终止执行任何清理操作时向其发出信号。
在此示例中,我将工作线程保存为 self.worker2
并阻止第二次启动工作线程,直到第一次完成为止。
import PyQt5
import PyQt5.QtCore as QtCore
from PyQt5.QtWidgets import *
import time
class Worker(QtCore.QThread):
def __init__(self, method_to_run):
super(Worker, self).__init__()
self.method = method_to_run
def run(self):
self.method()
class Window(QWidget):
def __init__(self):
super().__init__()
self.button = QPushButton('Test', self)
self.label = QLabel(self)
self.button.clicked.connect(self.handleButton)
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.button)
self.worker = Worker(self.test_method)
self.worker.start()
self.worker2 = None
def handleButton(self):
self.label.setText('Button Clicked!')
# likely better to disable the button instead... but
# this shows events in action.
if self.worker2:
self.label.setText('Worker already running')
else:
self.worker2 = Worker(self.test_method)
self.worker2.finished.connect(self.handle_worker2_done)
self.worker2.start()
def handle_worker2_done(self):
self.worker2 = None
self.label.setText('Worker done')
@staticmethod
def test_method():
#res = [i*i for i in range(100500)]
time.sleep(3)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
关于Python 在 PyQt5 应用程序中因 2 个工作线程而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43188123/