首页 > 解决方案 > PyQt5,QThread:如何在线程中运行非循环函数时保持 GUI 响应?

问题描述

我到目前为止基本上是这样的:

from PyQt5 import QtCore
import time

class WorkerThread(QtCore.QThread):
    def __init__(self, app, ml, parent=None):
        self.p = app
        self.ml = ml
        QtCore.QThread.__init__(self, parent)

    def run(self):
        self.ml()

class HelperClassForGUI:
    def __init__(self, app):
        self.p = app

    def mainFunc(self):
        self.thread = WorkerThread(self.p, SomeHeavyFunction)
        self.thread.finished.connect(self.done)
        self.thread.start()

    def done(self):
        ...

所以我有一个来自外部库的函数('SomeHeavyFunction')(所以我无法控制它),如果正常调用,它需要几秒钟才能完成并因此冻结 GUI,所以我想使用一个线程来同时保持 GUI 响应。

问题是,应用程序仍然冻结。'done()' 函数按原样执行,因此我可以假设具有该函数的线程实际上已正确终止,但没有出现预期的效果。

为了测试,我尝试了一个这样的函数,而不是实际的“SomeHeavyFunction”:

def func(self):
    self.idx = 0
    while self.idx < 100:
        if (self.idx % 3 == 0):
            self.p.statusBar.showMessage('Calculating ..')
        elif (self.idx % 3 == 1):
            self.p.statusBar.showMessage('Calculating. .')
        elif (self.idx % 3 == 2):
            self.p.statusBar.showMessage('Calculating.. ')
        self.idx += 1
        time.sleep(1)

有了这个,GUI 保持响应,但在这里我有一个不同的问题,如果我在线程期间尝试与 GUI 交互过多(例如,尝试显示更大的工具提示)或者如果我减少等待,GUI 经常崩溃时间从 1 秒到 0.1 秒。

所以,我的问题是:我错过了什么?我需要做什么才能使 GUI 保持响应并且不会崩溃?如上所述,我无法访问 SomeHeavyFunction,我只能调用它,但不能将其拆分为可循环的部分或类似的东西(我从大多数教程中看到的是他们会调用“processEvents”来保持 GUI 响应他们的线程通常是某种简单的循环,我不能真正将其应用于我的问题)。

编辑:重点是“不是循环的功能”。我无法控制 SomeHeavyFunction()。它不包含循环,我没有任何方法可以从其中发送任何周期性信号。我需要的是 SomeHeavyFunction() 是在某个(异步?)线程中启动的,只要 GUI 同时保持响应,它就可以根据需要进行。所以,基本上是一个“背景”线程。

标签: pythonmultithreadingpyqt5qthread

解决方案


推荐阅读