Terminating Qthread Gracefully On Qdialog Reject()
I have a QDialog which creates a QThread to do some work while keeping the UI responsive, based on the structure given here: How To Really, Truly Use QThreads; The Full Explanation
Solution 1:
Your problem is: self.thread
is freed by Python after the dialog is closed or the cancel button is pressed, while Qt thread is still running.
To avoid such situation, you can designate a parent to that thread. For example,
defrun(self):
# start the worker thread
self.thread = QtCore.QThread(self)
self.worker = Worker()
self.worker.moveToThread(self.thread)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('started()'), self.worker.process)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.thread.quit)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.worker.deleteLater)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('finished()'), self.thread.deleteLater)
self.thread.start()
Then it will be owned by Qt instead of PyQt and hence won't be collected by GC before it is terminated by Qt gracefully. Actually, this method just lets Qt not complain and doesn't solve the problem completely.
To terminate a thread gracefully, the common approach is using a flag to inform the worker function to stop. For example:
classWorker(QtCore.QObject):
def__init__(self):
QtCore.QObject.__init__(self)
defprocess(self):
# dummy worker process
self.flag = Falsefor n inrange(0, 10):
if self.flag:
print'stop'breakprint'process {}'.format(n)
time.sleep(0.5)
self.finished.emit()
finished = QtCore.pyqtSignal()
classDialog(QtGui.QDialog):
def__init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.init_ui()
definit_ui(self):
self.layout = QtGui.QVBoxLayout(self)
self.btn_run = QtGui.QPushButton('Run', self)
self.layout.addWidget(self.btn_run)
self.btn_cancel = QtGui.QPushButton('Cancel', self)
self.layout.addWidget(self.btn_cancel)
QtCore.QObject.connect(self.btn_run, QtCore.SIGNAL('clicked()'), self.run)
QtCore.QObject.connect(self.btn_cancel, QtCore.SIGNAL('clicked()'), self.reject)
QtCore.QObject.connect(self, QtCore.SIGNAL('rejected()'), self.stop_worker)
self.show()
self.raise_()
defstop_worker(self):
print'stop'
self.worker.flag = Truedefrun(self):
# start the worker thread
self.thread = QtCore.QThread(self)
self.worker = Worker()
self.worker.moveToThread(self.thread)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('started()'), self.worker.process)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.thread.quit)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.worker.deleteLater)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('finished()'), self.thread.deleteLater)
self.thread.start()
Post a Comment for "Terminating Qthread Gracefully On Qdialog Reject()"