Я пытаюсь объединить QThread и многопроцессорность, чтобы иметь возможность запускать некоторые длительные задачи обработки, сохраняя при этом мой GUI отзывчивым и обновленным со статусом процесса.
Следующий код не обновляет до тех пор, пока не закончится полный процесс, поэтому я вижу только последнее сообщение. Но print
работает нормально.
import time
from PySide2.QtWidgets import QApplication, QLabel, QWidget, QPushButton, QHBoxLayout
from PySide2.QtCore import QThread, QObject, Signal
from multiprocessing import Process, Queue
class Worker():
"""Worker running in a Process"""
def __init__(self):
self.r0 = 2
self.N = 10
def setR0(self, r0):
self.r0 = r0
def setN(self, n):
self.N = n
def task(self, queue):
for i in range(self.N):
res = self.r0 ** i
queue.put(str(i) + ": " + str(res))
time.sleep(1)
queue.put("done")
class Runner(QObject):
"""Runner is running in a qthread"""
messageLogged = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
def exec_(self):
worker = Worker()
worker.setN(15)
worker.setR0(3)
queue = Queue()
process = Process(target=worker.task, args=(queue,))
process.start()
while True:
msg = queue.get()
if msg == "done":
self.messageLogged.emit("received 'done' signal")
break
self.messageLogged.emit(msg)
process.join()
if __name__ == '__main__':
app = QApplication([])
widget = QWidget()
layout = QHBoxLayout()
widget.setLayout(layout)
button = QPushButton("Run")
layout.addWidget(button)
label = QLabel("initial text")
layout.addWidget(label)
thread = QThread()
r = Runner()
r.messageLogged.connect(print)
r.messageLogged.connect(label.setText)
thread.started.connect(r.exec_)
def onButtonPushed():
thread.start()
button.setEnabled(False)
button.clicked.connect(onButtonPushed)
widget.show()
app.exec_()
Чего мне не хватает, чтобы интерфейс реагировал? У меня такое ощущение, что мой слушатель l oop также должен быть Process
, но тогда как мне подать сигнал, который можно подключить к моей метке?