Despite saving a reference to the QThread
as self.lightsThread
, stopping the QObject
self.lightsWorker
then starting self.lightsThread
again caused the error
QThread: Destroyed while thread is still running
After stopping self.lightsWorker
, must the QThread
self.lightsThread
be stopped too? If not, what seems to be the problem?
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_())
following the answer https://stackoverflow.com/a/32138213/7742341 after stopping lightWorker
you should to quit from the thread and wait untill it is stopped
def stopLightsThread(self):
print('stop lightsThread')
self.lightsWorker.stop()
self.lightsThread.quit()
self.lightsThread.wait()
I had to face the same issue in C++, but the problem is the same.
The problem is that your QThread instance is deleted while the associated thread is still running. This can be really dangerous because the thread code execution is interrupted whitout any guarantee that the thread is ready to be deleted.
For example :
It lead to a memory leak and a ressource leak.
In your code, the worker is stopped, but not the working thread. I'm not python expert, but it also seems that your worker object is stopped but not deleted.
To properly stop your worker and thread, you should :
The last step is optionnal : if the thread and worker does not share ressources whith other object, you probably don't need to wait them to finish, just forget about them.
The only execption is that all your thread should be properly stopped before exiting the application : you should wait for all current running threads to stop before application exit.
For simple tasks, you should also consider using QtConcurrent framework.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With