如何在PyQt中停止正在运行的QThread进程?

问题描述 投票:0回答:1

我有一个 PyQt6 应用程序,旨在检测对象。我将 QThread 继承到一个名为“StartProcessWorkerThread”的用户定义类,以便在用户单击启动按钮(QPushButton)后创建一个工作实例。

这是继承自QThread类的worker类

class StartProcessWorkerThread(QThread):

processing_finished = pyqtSignal(dict)  # Signal for determining if the thread/worker has finished
progress_updated = pyqtSignal(int)  # Signal for determining if the progress bar value was updated

# Initialization
def __init__(self, input_video_filepaths, weapons_to_detect, clothings_to_detect_and_colors, username):
    super().__init__()
    self.input_video_filepaths = input_video_filepaths
    self.weapons_to_detect = weapons_to_detect
    self.clothings_to_detect_and_colors = clothings_to_detect_and_colors
    self.username = username

# Run method that emits the resulting data after running the method run_main_driver_code()
def run(self):
    table_data = self.run_main_driver_code()
    self.processing_finished.emit(table_data)

# This method is ran by run() method which runs the imported main_driver_code() from another .py file
def run_main_driver_code(self):
    user_specific_table_data = cwd.main_driver_code(
        input_video_filepaths = self.input_video_filepaths,
        weapons_to_detect = self.weapons_to_detect,
        clothings_to_detect_and_colors = self.clothings_to_detect_and_colors,
        username=self.username,
        progress_callback=self.progress_updated
    )

    return user_specific_table_data # returns the data returned by the imported main_driver_code() function or method from another .py file

从 QMainWindow() 实例(即应用程序的主窗口)中,单击开始按钮后,将调用一个方法,该方法创建工作程序或线程实例并使用其方法来启动或运行 cwd.main_driver_code() 早些时候。这就是实例的创建方式、启动方式和运行方式:

  self.worker = StartProcessWorkerThread(filtered_video_filepaths, weapons_to_detect, clothings_to_detect_and_colors, self.userloginname.text()) # Create thread worker instance and pass necessary parameters
  # Start running the thread worker instance to detectm generate table data, and update QTableWidget in main section with it
  self.worker.start() 
  # When the PyQt signal (progress_updated) gets updated from detect_weapon.py or detect_clothings.py, update the value of QProgressBar with the emitted value (detect_weapon.py - Line 255; detect_clothings.py - Line 290)
  self.worker.progress_updated.connect(self.updateProgressBar) 
  # When the PyQt signal (processing_finished) is finished, update the table data by executing self.updateTableData
  self.worker.processing_finished.connect(self.updateTableData) 
  # Enable input widgets after the thread worker is finished detecting and providing the table data
  self.worker.finished.connect(self.disableEnableDetectionButtons) 
  # Show Start Button again and hide the Progress Bar
  self.worker.finished.connect(self.hideUnhideStartButtonAndProgressBar)

我尝试了方法 quit()exit() 但这些方法没有停止或 StartProcessWorkerThread(QThread) 实例。我还尝试了 terminate() 方法来停止进程,但再次按下或单击开始按钮后应用程序会挂起并崩溃。

有人知道如何停止当前正在运行的 StartProcessWorkerThread(QThread) 实例吗?任何答案或建议将不胜感激。如果需要更多信息,请询问,我会尽力提供。请参阅注释以了解每行的详细信息或解释。预先感谢您。

pyqt pyqt5 pyqt6
1个回答
0
投票

这是一个关于如何停止正在运行的线程的最小示例。
回调函数有两个用途:发出

progress_update
信号,并返回
isInterruptionRequested()
的值。这样
long_process
就可以通过检查回调函数的返回值来知道是否应该继续。

import time
from typing import Callable

from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout
from PyQt6.QtCore import QThread, pyqtSignal


class Worker(QThread):
    progress_update = pyqtSignal(int)

    def run(self):
        long_process(self.callback)

    def callback(self, update: int):
        self.progress_update.emit(update)
        return self.isInterruptionRequested()


def long_process(callback: Callable):
    for i in range(1000):
        time.sleep(0.5)
        if callback(i):
            break


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.worker = Worker()
        label = QLabel()
        self.worker.progress_update.connect(lambda i: label.setText(str(i)))
        self.worker.finished.connect(lambda: label.setText('finished'))

        p1 = QPushButton('start')
        p2 = QPushButton('stop')

        p1.clicked.connect(self.worker.start)
        p2.clicked.connect(self.worker.requestInterruption)

        layout = QVBoxLayout(self)
        layout.addWidget(label)
        layout.addWidget(p1)
        layout.addWidget(p2)


app = QApplication([])
win = Window()
win.show()
app.exec()
© www.soinside.com 2019 - 2024. All rights reserved.