PyQt QThread:线程仍然存在时被销毁 运行
PyQt QThread: Destroyed while thread is still running
尽管将对 QThread
的引用保存为 self.lightsThread
,停止 QObject
self.lightsWorker
然后再次启动 self.lightsThread
导致了错误
QThread: Destroyed while thread is still running
停止self.lightsWorker
后,QThread
self.lightsThread
也必须停止吗?如果不是,似乎是什么问题?
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import time
class Screen(QMainWindow):
def __init__(self):
super(Screen, self).__init__()
self.initUI()
def initUI(self):
self.lightsBtn = QPushButton('Turn On')
self.lightsBtn.setCheckable(True)
self.lightsBtn.setStyleSheet("QPushButton:checked {color: white; background-color: green;}")
self.lightsBtn.clicked.connect(self.lightsBtnHandler)
self.setCentralWidget(self.lightsBtn)
def lightsBtnHandler(self):
if self.lightsBtn.isChecked():
self.startLightsThread()
else:
self.stopLightsThread()
def startLightsThread(self):
print 'start lightsThread'
self.lightsThread = QThread()
self.lightsWorker = LightsWorker()
self.lightsWorker.moveToThread(self.lightsThread)
self.lightsThread.started.connect(self.lightsWorker.work)
self.lightsThread.start()
def stopLightsThread(self):
print 'stop lightsThread'
self.lightsWorker.stop()
class LightsWorker(QObject):
signalFinished = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self._mutex = QMutex()
self._running = True
@pyqtSlot()
def work(self):
while self._running:
print 'working'
time.sleep(1)
self.signalFinished.emit()
@pyqtSlot()
def stop(self):
print 'Stopping'
self._mutex.lock()
self._running = False
self._mutex.unlock()
app = QApplication(sys.argv)
window = Screen()
window.show()
sys.exit(app.exec_())
按照答案 停止后 lightWorker
你应该退出线程并等待它停止
def stopLightsThread(self):
print('stop lightsThread')
self.lightsWorker.stop()
self.lightsThread.quit()
self.lightsThread.wait()
我不得不在 C++ 中面对同样的问题,但问题是一样的。
问题是您的 QThread 实例被删除,而关联的线程仍然 运行。这可能非常危险,因为线程代码执行被中断,但没有任何保证线程已准备好被删除。
例如:
- 线程控制对象(worker)的执行和生命周期
- 在此对象析构函数中释放资源(显式或隐式,就像使用 QObject parent/child 系统时一样)
- 由于线程执行中断,对象不会被删除
它会导致内存泄漏和资源泄漏。
在您的代码中,worker 停止了,但工作线程没有停止。我不是 python 专家,但您的 worker 对象似乎已停止但未删除。
要正确停止您的工作程序和线程,您应该:
- 向您的工作人员发送消息,告诉它 "stop working"
- 要求您的线程退出:它将 post 一条 "exit" 消息发送到线程,该线程将在 worker 执行后处理
- 等待您的线程停止
最后一步是可选的:如果线程和工作线程不与其他对象共享资源,您可能不需要等待它们完成,只需忘记它们即可。
唯一的例外是在退出应用程序之前应正确停止所有线程:在退出应用程序之前应等待所有当前 运行 线程停止。
对于简单的任务,您还应该考虑使用 QtConcurrent 框架。
尽管将对 QThread
的引用保存为 self.lightsThread
,停止 QObject
self.lightsWorker
然后再次启动 self.lightsThread
导致了错误
QThread: Destroyed while thread is still running
停止self.lightsWorker
后,QThread
self.lightsThread
也必须停止吗?如果不是,似乎是什么问题?
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import time
class Screen(QMainWindow):
def __init__(self):
super(Screen, self).__init__()
self.initUI()
def initUI(self):
self.lightsBtn = QPushButton('Turn On')
self.lightsBtn.setCheckable(True)
self.lightsBtn.setStyleSheet("QPushButton:checked {color: white; background-color: green;}")
self.lightsBtn.clicked.connect(self.lightsBtnHandler)
self.setCentralWidget(self.lightsBtn)
def lightsBtnHandler(self):
if self.lightsBtn.isChecked():
self.startLightsThread()
else:
self.stopLightsThread()
def startLightsThread(self):
print 'start lightsThread'
self.lightsThread = QThread()
self.lightsWorker = LightsWorker()
self.lightsWorker.moveToThread(self.lightsThread)
self.lightsThread.started.connect(self.lightsWorker.work)
self.lightsThread.start()
def stopLightsThread(self):
print 'stop lightsThread'
self.lightsWorker.stop()
class LightsWorker(QObject):
signalFinished = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self._mutex = QMutex()
self._running = True
@pyqtSlot()
def work(self):
while self._running:
print 'working'
time.sleep(1)
self.signalFinished.emit()
@pyqtSlot()
def stop(self):
print 'Stopping'
self._mutex.lock()
self._running = False
self._mutex.unlock()
app = QApplication(sys.argv)
window = Screen()
window.show()
sys.exit(app.exec_())
按照答案 停止后 lightWorker
你应该退出线程并等待它停止
def stopLightsThread(self):
print('stop lightsThread')
self.lightsWorker.stop()
self.lightsThread.quit()
self.lightsThread.wait()
我不得不在 C++ 中面对同样的问题,但问题是一样的。
问题是您的 QThread 实例被删除,而关联的线程仍然 运行。这可能非常危险,因为线程代码执行被中断,但没有任何保证线程已准备好被删除。
例如:
- 线程控制对象(worker)的执行和生命周期
- 在此对象析构函数中释放资源(显式或隐式,就像使用 QObject parent/child 系统时一样)
- 由于线程执行中断,对象不会被删除
它会导致内存泄漏和资源泄漏。
在您的代码中,worker 停止了,但工作线程没有停止。我不是 python 专家,但您的 worker 对象似乎已停止但未删除。
要正确停止您的工作程序和线程,您应该:
- 向您的工作人员发送消息,告诉它 "stop working"
- 要求您的线程退出:它将 post 一条 "exit" 消息发送到线程,该线程将在 worker 执行后处理
- 等待您的线程停止
最后一步是可选的:如果线程和工作线程不与其他对象共享资源,您可能不需要等待它们完成,只需忘记它们即可。
唯一的例外是在退出应用程序之前应正确停止所有线程:在退出应用程序之前应等待所有当前 运行 线程停止。
对于简单的任务,您还应该考虑使用 QtConcurrent 框架。