在线程启动时将Args传递给PyQt工作线程

时间:2017-09-19 17:22:12

标签: python multithreading pyqt

我正在尝试学习Python和PyQt,虽然它的性能很好,但我在PyQt线程方面遇到了巨大的问题。我已经使用Python"线程"很好地工作了。模块,虽然我偶然发现了Seg Fault错误(没有附加信息)。

我想学习如何正确地使用PyQt进行线程化。我已经阅读了#34;你做错了#34;,"你没有这么做错#",Maya Posch的帖子,(跛脚)PyQt4和(稍微不那么蹩脚)PyQt5文档,以及大量有关如何操作的教程和示例(包括来自Stack-O的批量)和我只是变得越来越困惑。

我已经能够获得线程来启动Worker并执行其操作并返回数据。我可以毫无问题地退出,发射等,但是我无法将任何args传递给Worker。我是一个相当聪明的人,但这让我觉得自己像个完全白痴!每当我读到新的东西并尝试它时,我觉得我试图将一个方形钉子推入一个圆孔。

我正在使用" moveToThread"功能,而不是线程的子类,根据我读过的大多数帖子,这是正确的方法(虽然大多数例子显示为子类)。

我不是故意听起来像一个刺,但如果你可以帮助我,那么我需要的不仅仅是"只要你做什么就发送它" - 我需要一个真实的例子或明确的东西。我已经看到有人接近回答这个问题,但是他们非常模糊,Stack-O要求我有22个以上的声望点,以便我对其他人的帖子发表评论或提问...... ~~叹息

我有一个模拟我的大脚本的存根脚本。以下是存根中的相关代码:

def pre_Flight_Check():
    #count = 0 # I want to pass THIS to the Worker at Worker's start
    fire_Up_Thread(count)
#=====================
def butStop_click():
    # Stop Loop/Thread:
    flagQuit = flagQuit + 1
#=====================
# Worker:
class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    @pyqtSlot()
    def looper(self):
        flagQuit = 0
        count = 0 # I'd like to pass this into the Worker, not define it here
        while (count < 5):
            self.intCount.emit(count)
            time.sleep(1)
            count = count + 1
            if flagQuit != 0:
                break        
        self.finished.emit()
#========================
objWorker = Worker()
thrWorker = QThread()
#========================
# Threading stuffs:
def fire_Up_Thread(count):
    # NOTE: I CAN pass the "count" var into here, just not to the Worker
    objWorker.moveToThread(thrWorker)
    thrWorker.started.connect(objWorker.looper)
    objWorker.intCount.connect(updateTextBox)
    objWorker.finished.connect(thrWorker.quit)
    objWorker.finished.connect(work_finished)        
    # Start the thread:
    thrWorker.start()

仅供参考:这是使用Python线程的实现 - 它非常简单直接:

# Loop
def looper(count):
    flagQuit = 0

    while (count < 5):
        print(count)
        txtBox1.setText(str(count))
        time.sleep(1)
        count = count + 1
        # User clicked "Stop" button
        if flagQuit != 0:
            break
    work_finished()
#========================
def pre_Flight_Check():
    # Var(s) to send to thread:
    count = 0
    # Start Loop/Thread
    loopTest = threading.Thread(target=looper, args=(count,))
    loopTest.setDaemon(True)
    loopTest.start()

2 个答案:

答案 0 :(得分:0)

初始化Worker

时,只需传递参数即可
class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    def __init__(self, count):
        super(Worker, self).__init__()
        self.count = count

    @pyqtSlot()
    def looper(self):
        flagQuit = 0
        while (self.count < 5):
            self.intCount.emit(self.count)
            time.sleep(1)
            self.count = self.count + 1
            if flagQuit != 0:
                break        
        self.finished.emit()


count = 0
objWorker = Worker(count)

答案 1 :(得分:0)

使用&#34;部分&#34;来自&#34; functools&#34; module允许变量被视为可调用的,然后可以使用该变量将args传递给Worker。这是原始行:

thrWorker.started.connect(objWorker.looper)

和修改后的行:

thrWorker.started.connect(partial(objWorker.looper,count,strIs))

现在重新编写整个存根以包含更改:

def pre_Flight_Check():
    count = 0
    strIs = "is: " # NOTE: this is only here to show that more than 1 variable can be included
    fire_Up_Thread(count,strIs) # 2 vars to pass
#=====================
def butStop_click():
    flagQuit = flagQuit + 1
#=====================
# Worker:
class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    @pyqtSlot()
    def looper(self,count,strIs): # Both vars - "count" and "strIs"
        flagQuit = 0
        while (count < 5):
            strCount = "The count " + strIs + str(count)
            self.intCount.emit(count)
            time.sleep(1)
            count = count + 1
            # User clicked "Stop" button
            if flagQuit != 0:
                break
        self.finished.emit()
#========================
objWorker = Worker()
thrWorker = QThread()
#========================
# Threading stuffs:
def fire_Up_Thread(count,strIs): # Passed in from "pre_Flight_Check"
    from functools import partial
    objWorker.moveToThread(thrWorker)
    thrWorker.started.connect(partial(objWorker.looper,count,strIs)) # All vars are appended to connected target
    objWorker.intCount.connect(updateTextBox)
    objWorker.finished.connect(thrWorker.quit)
    objWorker.finished.connect(work_finished)
    # Start the thread:
    thrWorker.start()

这是有效的,它是线程安全的,它在处理方面很快且成本很低。