pyqtSignals没有在QThread worker中发出 [英] pyqtSignals not emitted in QThread worker
问题描述
我有一个BackgroundTask
对象的实现,如下所示:
I have an implementation of a BackgroundTask
object that looks like the following:
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
正如我的文档字符串所示,这应该允许我将任意的callable
及其参数传递给build_and_run_background_task
,并且在完成任务后,它应该调用以finished_notifier
传递的callable
并杀死线程.但是,当我使用以下命令作为finished_notifier
As my docstrings indicate, this should allow me to pass an arbitrary callable
and its arguments to build_and_run_background_task
, and upon completion of the task it should call the callable
passed as finished_notifier
and kill the thread. However, when I run it with the following as finished_notifier
def done():
flushed_print('Done!')
我得到以下输出:
Setting Up Background Task To Run In Thread
Thread Started!
Running Task
Got My Results!
Emitting Finished!
就是这样. finish_notifier回调不会执行,线程的quit方法也不会调用,这表明实际上未发出BackgroundTask
中的finshed
信号.但是,如果我直接绑定到finshed
并直接调用runTask
(不在线程中),则一切都会按预期进行.我确定我只是想念一些愚蠢的东西,有什么建议吗?
And that's it. The finished_notifier callback is never executed, and the thread's quit method is never called, suggesting the finshed
signal in BackgroundTask
isn't actually being emitted. If, however, I bind to finshed
directly and call runTask
directly (not in a thread), everything works as expected. I'm sure I just missed something stupid, any suggestions?
推荐答案
我自己弄清楚了这个问题,我需要调用qApp.processEvents()
,其中应用程序中的另一点正在等待此操作完成.我也在命令行上进行了测试,并且掩盖了相同的问题.
Figured out the problem myself, I needed to call qApp.processEvents()
where another point in the application was waiting for this operation to finish. I had been testing on the command-line as well and that had masked the same problem.
这篇关于pyqtSignals没有在QThread worker中发出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!