从继承 QThread 迁移到 Worker 模型 [英] migrating from Inherited QThread to Worker model

查看:49
本文介绍了从继承 QThread 迁移到 Worker 模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以通过我之前问题中的很多帮助(中断 QThread 睡眠PySide 将信号从 QThread 传递到另一个 QThread) 我决定尝试从继承的 QThread 模型更改为 Worker 模型.我想我应该继续使用 QThread 模型,因为我有那个工作,而另一个模型不是.但是我不确定为什么 Worker 模型对我不起作用.

So through a lot of help in my previous questions (Interrupting QThread sleep and PySide passing signals from QThread to a slot in another QThread) I decided to attempt to change from the inherited QThread model to the Worker model. I am thinking I should stay with the QThread model as I had that working, and the other model is not. However I am not sure why the Worker model isn't working for me.

我正在尝试这样做,请让我知道我的方法论是否存在固有的错误?

I am attempting to do this please let me know if there is something inherently wrong in my methodology?

我有一个 QtGui.QWidget 是我的主要 GUI.我正在使用 QPushButton 来发出信号我试图将代码简化为我认为问题所在的基础知识.我已经验证 datagramHandled Signal 被发出,但 packet_handled Slot 似乎没有被调用.>

I have a QtGui.QWidget that is my main GUI. I am using a QPushButton to signal I have attempted to reduce the code to the basics of where I believe the issue is. I have verified that datagramHandled Signal gets emitted but the packet_handled Slot doesn't seem to get called.

class myObject(QtCore.QObject):
    def __init__(self):
        super(myObject, self).__init__()
        self.ready=False

    @QtCore.Slot()
    def do_work(self):
        #send a packet
        self.ready=False
        while not self.ready:
            time.sleep(0.01)

    @QtCore.Slot(int)
    def packet_handled(self, errorCode):
        print "Packet received."
        self.ready = True

class myWidget(QtGui.QWidget):
    datagramHandled = QtCore.Signal(int)
    startRunThread = QtCore.Signal()
    def __init__(self,parent=None, **kwargs):
        super(myWidget, self).__init__(parent=parent)
        # Bunch of GUI setup stuff (working)
        self.myRunThread = QtCore.QThread()
    @QtCore.Slot()
    def run_command(self):
        self.myRunObj = myObject()
        self.myRunObj.moveToThread(self.myRunThread)
        self.datagramHandled.connect(self.myRunObj.packet_handled)
        self.startRunThread.connect(self.myRunObj.do_work)
        self.myRunThread.start()
        self.startRunThread.emit()

    @QtCore.Slot()
    def handle_datagram(self):
        #handle the incoming datagram
        errorCode = 0
        self.datagramHandled.emit(errorCode)

推荐答案

第一个问题是你需要将你的myObject.do_work方法连接到QThread.started:

The first issue is that you need to connect your myObject.do_work method to QThread.started:

self.myRunThread.started.connect(self.myRunObj.do_work)

其次,您的 do_work 方法应该包含一些类似这些内容以启用事件处理(请原谅我生疏的 PyQt 和伪代码):

Secondly, your do_work method should include something along these lines to enable event processing (please forgive my rusty PyQt and pseudocode):

def do_work(self):
    while someCondition:
        #The next two lines are critical for events and queued signals
        if self.thread().eventDispatcher().hasPendingEvents():
            self.thread().eventDispatcher().processEvents(QEventLoop.AllEvents)
        if not self.meetsSomeConditionToContinueRunning():
            break
        elif self.hasWorkOfSomeKind():
            self.do_something_here()
        else:
            QThread.yieldCurrentThread()

有关这方面的更多信息,请查看 QAbstractEventDispatcher.

For more on this, check out the docs for QAbstractEventDispatcher.

这里的逻辑是,当从一个线程 (myWidget.datagramHandled) 发出信号时,它会在您的工作线程的事件循环中排队.调用 processEvents 处理任何挂起的事件(包括排队的信号,它们实际上只是事件),为任何排队的信号调用适当的槽 (myRunObj.packet_handled).

The logic here is that when a signal is emitted from one thread (myWidget.datagramHandled), it gets queued in your worker thread's event loop. Calling processEvents processes any pending events (including queued signals, which are really just events), invoking the appropriate slots for any queued signals (myRunObj.packet_handled).

进一步阅读:

这篇关于从继承 QThread 迁移到 Worker 模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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