pyqtSignals没有在QThread worker中发出 [英] pyqtSignals not emitted in QThread worker

查看:67
本文介绍了pyqtSignals没有在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆