Я делаю несколько многопотоков. У меня есть рабочий класс с методом work
, который я отправляю в отдельный QThread
. Метод work
имеет условный цикл внутри. Я хочу, чтобы можно было отправить сигнал рабочему объекту, чтобы остановить его (изменение условия _running
на false). Это вызовет выход цикла while и готовый сигнал, который будет отправлен из рабочего объекта (который подключен к слоту выхода из потока рабочего).PyQt: Как отправить сигнал остановки в поток, в котором объект работает в замкнутом цикле?
Ложное условие отправляется объекту-работнику по сигналу, но оно никогда не принимается, что я считаю потому, что цикл while блокирует цикл событий его потока. Даже если я поставлю QCoreApplication.processEvents()
внутри цикла while, ничего не произойдет. В чем проблема? Почему сигнал не обрабатывается? (Обратите внимание, что оператор печати в слоте остановки на рабочем месте никогда не выполняется, но, как ни странно, поток, похоже, не работает неправильно).
Вот код:
import time, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Worker(QObject):
sgnFinished = pyqtSignal()
def __init__(self, parent):
QObject.__init__(self, parent)
self._running = True
@pyqtSlot()
def stop():
print 'stop signal received, switching while loop condition to false'
self._running = False
@pyqtSlot()
def work(self):
while self._running: #this blocks the thread, if changed to an if clause, thread finishes as expected!
QCoreApplication.processEvents() #this doesn't help!
time.sleep(0.1)
print 'doing work...'
#do some cleanup here, then signal the worker is done
self.sgnFinished.emit()
class Client(QObject):
sgnStop = pyqtSignal()
def __init__(self, parent):
QObject.__init__(self, parent)
self._thread = None
self._worker = None
def toggle(self, enable):
if enable:
if not self._thread:
self._thread = QThread()
self._worker = Worker(None)
self._worker.moveToThread(self._thread)
self._worker.sgnFinished.connect(self.on_worker_done)
self.sgnStop.connect(self._worker.stop)
self._thread.started.connect(self._worker.work)
self._thread.start()
else:
print 'sending stop signal to the worker object'
self.sgnStop.emit() #send a queuedconnection type signal to the worker, because its in another thread
@pyqtSlot()
def on_worker_done(self):
print 'workers job was interrupted manually'
self._thread.quit()
#self._thread.wait() not sure this is neccessary
if __name__ == '__main__':
app = QCoreApplication(sys.argv)
client = Client(None)
client.toggle(True)
raw_input('Press something')
client.toggle(False)
http://stackoverflow.com/questions/32952474/non-blocking-worker-interrupt-file-copy – dtech
Я нашел решение, которое я не понимаю. Замена объявления соединения с сигналом останова с этим (добавление обработчика как выражения лямбда) устраняет проблему: self.sgnStop.connect (lambda: self._worker.stop()) – U2ros
Ну, не совсем работает, кажется, sgnFinished никогда уволен из метода работы, поэтому on_worker_done никогда не вызывается на клиенте. – U2ros