Kar Kar - 1 month ago 18
Python Question

'QThread: Destroyed while thread is still running' on quit

I'm trying to find a way to quit my app properly. When I exit, I get an error saying

QThread: Destroyed while thread is still running
. I have a thread for feeding output to a
QTextBrowser
. What should be the proper way to exit? Here's what I've got:

class LogReceiver(QtCore.QObject):
mysignal = QtCore.Signal(str)

def __init__(self, queue, *args, **kwargs):
QtCore.QObject.__init__(self, *args, **kwargs)
self.queue = queue

def run(self):
while True:
text = self.queue.get()
self.mysignal.emit(text)

if __name__ == '__main__':
queue = Queue()
thread = QtCore.QThread()
my_receiver = MyReceiver(queue)

app = QApplication(sys.argv)
window = MainWindow()
window.show()

my_receiver.mysignal.connect(window.append_text)
my_receiver.moveToThread(thread)
thread.started.connect(my_receiver.run)
thread.start()

sys.exit(app.exec_())


Should
thread
somehow be terminated upon exit? Note that
self.queue.get()
blocks and waits for text.

Thanks

Answer

You need to re-structure the while loop so that it doesn't block uncondtionally.

You can do this with a simple flag and a timeout:

    def run(self):
        self.active = True
        while self.active:
            try:
                text = self.queue.get(timeout=1.0)
                self.mysignal.emit(text)
            except Empty:
                continue

So now the queue won't block indefinitely, and the flag will be checked once a second to see if the loop should be exited.

EDIT:

Here's a working example based on your code:

import sys
from queue import Queue, Empty
from PySide import QtCore, QtGui

class LogReceiver(QtCore.QObject):
    mysignal = QtCore.Signal(str)

    def __init__(self, queue, *args, **kwargs):
        QtCore.QObject.__init__(self, *args, **kwargs)
        self.queue = queue

    def run(self):
        self.active = True
        while self.active:
            try:
                text = self.queue.get(timeout=1.0)
                self.mysignal.emit('text')
            except Empty:
                continue
        print('finished')

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.queue = Queue()
        self.thread = QtCore.QThread(self)
        self.receiver = LogReceiver(self.queue)
        self.receiver.moveToThread(self.thread)
        self.thread.started.connect(self.receiver.run)
        self.thread.start()

    def closeEvent(self, event):
        print('close')
        self.receiver.active = False
        self.thread.quit()
        self.thread.wait()

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()

    sys.exit(app.exec_())
Comments