【问题标题】:How to Run Thread While Main Thread Does Work? [closed]如何在主线程工作时运行线程? [关闭]
【发布时间】:2021-12-07 13:23:36
【问题描述】:

我正在编写的 Python 程序有一个非常特殊的问题,我需要一个进程同时运行,同时在主线程上执行一个长时间运行的函数

为了清楚/举例,假设我有 2 个必要的功能:

  1. 每秒将进度条增加 1 的函数
  2. 执行非常长时间(30 多秒)分析并且必须在主线程上运行的函数(没有例外,我已确认此规则没有解决方法)李>

这样,我需要这些同时运行,以便在运行分析时进度条增加。所以很自然地,我创建了一个线程来增加进度条并尝试在调用分析函数之前调用它,如下所示:

class ProgressThread(QThread):
    _signal = pyqtSignal(int)
    def __init__(self):
        super(Thread, self).__init__()
    def run(self):
        progress = True
        pct = 0
        while progress:     #while thread is running
            time.sleep(1)   #wait 1 sec
            pct += 1
            self._signal.emit(pct)  #emit signal to increment progressbar


class Window(QMainWindow):
    def __init__(self):
         self.progressbar = QProgressBar()  #init progressbar
    def main(self):
        self.thread = ProgressThread()
        self.thread._signal.connect(self.increment_progressbar)
        self.thread.start() #start progressbar incrementer thread

        result = long_analysis_function()   #start analysis function

    def increment_progressbar(self, percent):   #helper function to increment progressbar
        self.progressbar.setValue(percent)

但是,此代码会阻塞 ProgressThread,直到 long_analysis_function() 完成,因此进度条在分析过程中保持冻结状态,并在分析函数完成后跳转到 x%。

我相信这可以通过将分析函数移动到它自己的线程来解决,因为进度条和分析在这种情况下运行,但随后分析线程会因为不在“主线程”中而引发错误,所以我真的无法做到这一点。

这样,当分析函数在主线程中同时运行时,我怎样才能使我的进度条递增或线程正确?

【问题讨论】:

  • Re,“进度条...跳转到 x%”听起来可能线程 正在 正在运行,但 self._signal.emit(pct) 对图形用户界面。听起来您正在将 QTWidgets 用于您的 GUI 框架。我不知道 QT(我不知道何时/为什么/多久调用一次 Window.main() 函数)但我猜运行 long_analysis_function() 的“主”线程也是 GUI 线程.如果这是真的,那么在long_analysis_function() 返回之前,您不应该期望在屏幕上看到任何事情。
  • 如果没有看到long_analysis_function() 中的所有代码,就无法正确回答这个问题。因此,请提供minimal reproducible example

标签: python multithreading pyqt pyqt5 python-multithreading


【解决方案1】:

我在主窗口初始化时尝试实现动画启动屏幕时遇到了类似的问题。我从中学到的是,GUI 类只能从主线程(GUI 线程)进行更新或操作。

你必须同时做两个任务。

  1. 更新进度条(需要主线程)
  2. 做长分析(你坚持要在主线程中)

从逻辑上讲,这两个需要在单独的线程中才能实现。因为,两者都必须在主线程中,我想这是不可能的,或者至少很难实现。

而且,您的进度线程只是每秒增加百分比,而不是报告实际进度?虽然ProgressThread 每秒都在发出信号,但progressbar.setValue 在主线程繁忙时实际上无法更新。

一种解决方案可能是将长期分析分解为小任务,这样可以记住之前取得的进展并继续进行。然后,循环运行这些小任务。每完成一个小任务,更新进度条。这样,您也可以报告实际进度。或者,直接从long_analysis_function安排更新进度条

但请记住,当任何任务运行时,它会使整个 GUI 无响应。

更多阅读:

【讨论】:

    猜你喜欢
    • 2013-09-13
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多