如何在使用QWaitCondition的QThread中使用QTimer? (派赛德) [英] How to use QTimer inside QThread which uses QWaitCondition? (pyside)

查看:311
本文介绍了如何在使用QWaitCondition的QThread中使用QTimer? (派赛德)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用pyside,但是(我认为)是一个通用的Qt问题.

I'm using pyside but (I think) is a generic Qt question.

我知道QThread实现会调用._exec()方法,因此我们应该在启动的QThread上有一个事件循环.这样,我们就可以在该线程上使用QTimer(我已经做到了,它可以完美地工作).我的问题是,当还使用QWaitCondition时,我想要一个带有无限循环的消费者"线程,等待(从生产者处)在QWaitCondition上进行通知.我的问题是,使用这种设计,我无法在使用者线程内使用QTimer.

I know that QThread implementation calls ._exec() method so we should have an event loop on a started QThread. This way we can use QTimer on that thread (I've done this and it works perfectly). My problem is when QWaitCondition is also used, I'd like to have a "consumer" thread with a infinite loop waiting to be notify (from producers) on the QWaitCondition. The problem I have is that with this design I cannot use QTimer inside the consumer Thread.

这是我要解释的场景的摘要:

This is a snippet of the scenario I'm trying to explain:

from PySide import QtGui
from PySide import QtCore
import sys

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.button = QtGui.QPushButton(self)
        self.button.setText("Periodical")
        self.button.clicked.connect(self.periodical_call)

        self.thread = QtCore.QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.loop)
        self.thread.start()

    def closeEvent(self, x):
        self.worker.stop()
        self.thread.quit()
        self.thread.wait()

    def periodical_call(self):
        self.worker.do_stuff("main window") # this works
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.do_stuff) # this also works
        self.timer.start(2000)

    def do_stuff(self):
        self.worker.do_stuff("timer main window")

class Worker(QtCore.QObject):
    def do_stuff_timer(self):
        do_stuff("timer worker")

    def do_stuff(self, origin):
        self.origin = origin
        self.wait.wakeOne()

    def stop(self):
        self._exit = True
        self.wait.wakeAll()

    def loop(self):
        self.wait = QtCore.QWaitCondition()
        self.mutex = QtCore.QMutex()
        self._exit = False
        while not self._exit:
            self.wait.wait(self.mutex)

            print "loop from %s" % (self.origin,)

            self.timer = QtCore.QTimer()
            self.timer.setSingleShot(True)
            self.timer.timeout.connect(self.do_stuff_timer)
            self.timer.start(1000) # <---- this doesn't work

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    frame = MainWindow()
    frame.show()
    sys.exit(app.exec_())

单击按钮后,我们将获得如下输出:

Once you click the button we obtain an output like this:

loop from main window                    
loop from timer main window
loop from timer main window
loop from timer main window
...

这意味着在loop()方法内部创建的QTimer不会由事件循环执行.

This means that the QTimer created inside loop() method is never executed by the event loop.

如果我将设计从QWaitCondition更改为Signals(这是更好的设计,恕我直言),则QTimer可以工作,但是我想知道为什么在使用QWaitCondition时它们不起作用.

If I change the design from QWaitCondition to Signals (which is better design imho) the QTimer works, but I'd like to know why they are not working when QWaitCondition is used.

推荐答案

要在长时间运行的任务(又称连续循环)中仍处理事件,则需要调用

To still process events in a long running task (aka a continuous loop) you need to call QCoreApplication::processEvents().

这实际上将遍历线程的所有排队队列.

This will essentially go through all of the queued up slots for your thread.

对于信号(如果它们是QueuedConnection信号/插槽连接),要使其从当前线程进入另一个线程,也必须调用此函数.

Calling this function is also necessary for signals (if they are a QueuedConnection signal/slot connection) to make it out of the current thread and into another one.

对于PySides,您需要调用 PySide.QtCore.QCoreApplication.processEvents()

For PySides, you will need to call PySide.QtCore.QCoreApplication.processEvents()

这篇关于如何在使用QWaitCondition的QThread中使用QTimer? (派赛德)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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