pyqtSignals não emitidos no trabalhador QThread
Eu tenho uma implementação de umBackgroundTask
objeto que se parece com o seguinte:
class BackgroundTask(QObject):
'''
A utility class that makes running long-running tasks in a separate thread easier
:type task: callable
:param task: The task to run
:param args: positional arguments to pass to task
:param kawrgs: keyword arguments to pass to task
.. warning :: There is one **MAJOR** restriction in task: It **cannot** interact with any Qt GUI objects.
doing so will cause the GUI to crash. This is a limitation in Qt's threading model, not with
this class's design
'''
finished = pyqtSignal() #: Signal that is emitted when the task has finished running
def __init__(self, task, *args, **kwargs):
super(BackgroundTask, self).__init__()
self.task = task #: The callable that does the actual task work
self.args = args #: positional arguments passed to task when it is called
self.kwargs = kwargs #: keyword arguments pass to task when it is called
self.results= None #: After :attr:`finished` is emitted, this will contain whatever value :attr:`task` returned
def runTask(self):
'''
Does the actual calling of :attr:`task`, in the form ``task(*args, **kwargs)``, and stores the returned value
in :attr:`results`
'''
flushed_print('Running Task')
self.results = self.task(*self.args, **self.kwargs)
flushed_print('Got My Results!')
flushed_print('Emitting Finished!')
self.finished.emit()
def __repr__(self):
return '<BackgroundTask(task = {}, {}, {})>'.format(self.task, *self.args, **self.kwargs)
@staticmethod
def build_and_run_background_task(thread, finished_notifier, task, *args, **kwargs):
'''
Factory method that builds a :class:`BackgroundTask` and runs it on a thread in one call
:type finished_notifier: callable
:param finished_notifier: Callback that will be called when the task has completed its execution. Signature: ``func()``
:rtype: :class:`BackgroundTask`
:return: The created :class:`BackgroundTask` object, which will be running in its thread.
Once finished_notifier has been called, the :attr:`results` attribute of the returned :class:`BackgroundTask` should contain
the return value of the input task callable.
'''
flushed_print('Setting Up Background Task To Run In Thread')
bg_task = BackgroundTask(task, *args, **kwargs)
bg_task.moveToThread(thread)
bg_task.finished.connect(thread.quit)
thread.started.connect(bg_task.runTask)
thread.finished.connect(finished_notifier)
thread.start()
flushed_print('Thread Started!')
return bg_task
Como meus documentos indicam, isso deve permitir que eu passe umacallable
e seus argumentos parabuild_and_run_background_task
e, após a conclusão da tarefa, deve chamar ocallable
passou comofinished_notifier
e mate o fio. No entanto, quando eu o executo com o seguinte, comofinished_notifier
def done():
flushed_print('Done!')
Eu recebo a seguinte saída:
Setting Up Background Task To Run In Thread
Thread Started!
Running Task
Got My Results!
Emitting Finished!
E é isso. O retorno de chamada ended_notifier nunca é executado e o método de encerramento do thread nunca é chamado, sugerindo ofinshed
sinal emBackgroundTask
não está realmente sendo emitido. Se, no entanto, eu me vincular afinshed
diretamente e liguerunTask
diretamente (não em um thread), tudo funciona como esperado. Tenho certeza que perdi algo estúpido, alguma sugestão?