У меня есть QDialog, который создает QThread, чтобы выполнить некоторую работу, сохраняя отзывчивость пользовательского интерфейса на основе приведенной здесь структуры: How To Really, Truly Use QThreads; The Full Explanation. Однако, если отвергнуть() вызываются (из-за нажатие пользователя отмены или закрытия диалогового окна), а поток все еще работает, я получаю сообщение об ошибке:Прекращение QThread изящно на QDialog reject()
QThread: Destroyed while thread is still running
То, что я хотел бы случиться для цикла в работнику рано сломать, затем выполнить некоторую очистку в фоновом режиме (например, очистить некоторые очереди, испустить сигнал). Мне удалось сделать это с помощью моей собственной функции «отменить», но как мне заставить ее хорошо играть с reject() (и всевозможные способы ее вызова)? Я не хочу, чтобы диалог блокировал ожидание очистки - он должен просто работать в фоновом режиме, а затем изящно выйти.
См. Пример кода, ниже которого представлена проблема. Любая помощь будет принята с благодарностью.
#!/usr/bin/env python
from PyQt4 import QtCore, QtGui
import sys
import time
class Worker(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
def process(self):
# dummy worker process
for n in range(0, 10):
print 'process {}'.format(n)
time.sleep(0.5)
self.finished.emit()
finished = QtCore.pyqtSignal()
class Dialog(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
self.init_ui()
def init_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)
self.show()
self.raise_()
def run(self):
# start the worker thread
self.thread = QtCore.QThread()
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()
def main():
app = QtGui.QApplication(sys.argv)
dlg = Dialog()
ret = dlg.exec_()
if __name__ == '__main__':
main()
Использование этого метода можно получить основное приложение, чтобы ждать каких-либо нитей, чтобы очистить перед выходом? Я запускаю код как плагин в более крупном приложении (QGIS). – Snorfalorpagus
@snorfalorpagus: Я обновил свой пост. Я думаю, что использование флага - самый безопасный способ остановить поток. – nymk