终止带有for循环的多个QProcess的QThread

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

最近我问了question关于如何使用嵌套循环生成运行多个QProcess实例时如何防止QThread冻结GUI的问题。提供的解决方案就像魅力一样!我能够完成我的程序,并且运行顺利!我最近添加了一项功能,允许用户在此过程中的任何时候停止QThread。停止功能的工作原理是不会调用新的QProcesse实例。但是,仍有许多未完成的QProcess实例仍在处理中。有没有一种方法可以确定何时不再有任何QProcess实例正在运行并通知用户?我熟悉QProcess方法waitForFinished(),但是我不确定如何将其应用于使用嵌套循环生成的QProcess的多个实例。

这里是模拟我实际程序的数据处理方面的代码示例:

# This Python file uses the following encoding: utf-8
import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import test
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui=test.Ui_test()
        self.ui.setupUi(self)
        self.ui.pushButton_startThread.clicked.connect(self.startTestThread)
        self.ui.pushButton_Update.clicked.connect(self.stopThread)

    def startTestThread(self):
        self.xValue = self.ui.lineEdit_x.text() #Represents number of batches
        self.yValue = self.ui.lineEdit_y.text() #Represents number of images per batch
        self.runTest = testThread(self.xValue, self.yValue, self)  # Creates an instance of testThread
        self.runTest.start()  # Starts the instance of testThread

    def stopThread(self):
        self.runTest.stop()
        self.ui.lineEdit_x.setText("")
        self.ui.lineEdit_y.setText("")



class testThread(QThread):
    def __init__(self, xValue, yValue, parent=None):
        super().__init__(parent)
        self.xValue = xValue
        self.yValue = yValue

    def __del__(self):
        self.wait()

    def run(self):
        processd = []
        for x in range(int(self.xValue)):  # For loop to iterate througeach batch
            pass
            for y in range(
                int(self.yValue)):  # For loop to iterate through each image in each batch
                time.sleep(.1)
            QProcess.startDetached(os.path.dirname(os.path.realpath(__file__)) + r"\test.bat")  # Runs test.bat

    def stop(self):
        self.terminate()
        self.wait()
        print("\nStopping thread")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

test.bat

@ECHO OFF
ECHO Processing Batched Images.
TIMEOUT /T 15
ECHO Process Finished.

如前所述,停止QThread工作;但是,我希望能够确定何时完成所有QProcess实例。这将允许程序通知用户他们可以使用新参数重新启动过程。目前,我不得不告诉我的同事们等到不再写入任何输出文件,然后再尝试一组新的参数。

任何帮助将不胜感激。谢谢您的时间!

python-3.x pyqt5 qthread qprocess
1个回答
0
投票

虽然不是很优雅,但我想出了一种方法来确定终止QThread之后何时完成QProcess的多个实例:

  1. 我添加了一个批处理计数器,每当一个QProcess实例排队时,它就会增加一个。
  2. 一旦取消线程,当前批处理计数器就会发出信号。
  3. 该信号与一种方法有关,该方法将确定QProcess的所有实例何时完成处理。
  4. 对于我的程序,每个QProcess实例都会生成一个唯一的输出文件。
  5. 使用while循环,可以确定QProcess的所有实例完成的时刻。

这里是代码示例:

# This Python file uses the following encoding: utf-8
import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import test
import time
from glob import glob1

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui=test.Ui_test()
        self.ui.setupUi(self)
        self.ui.pushButton_startThread.clicked.connect(self.startTestThread)
        self.ui.pushButton_Update.clicked.connect(self.stopThread)

    def startTestThread(self):
        self.xValue = self.ui.lineEdit_x.text() #Represents number of batches
        self.yValue = self.ui.lineEdit_y.text() #Represents number of images per batch
        self.runTest = testThread(self.xValue, self.yValue, self)  # Creates an instance of testThread
        self.runTest.signals.batchesSubmitted.connect(self.testThreadFinished)
        self.runTest.start()  # Starts the instance of testThread

    def stopThread(self):
        self.runTest.stop()

    @pyqtSlot(int)    
    def testThreadFinished(self, batchesSubmitted):
        while len(glob1(outputFilePath + fileName, "*.txt")) < batchesSubmitted: #Compare the number of *.txt files in the output directory to the number of isntances of QProcess called
            time.sleep(1)
        self.ui.lineEdit_x.setText("")
        self.ui.lineEdit_y.setText("")
        print("All instance of QProcess are finished!")

class testThreadSignals(QObject):
    batchesSubmitted = pyqtSignal(int)

class testThread(QThread):
    def __init__(self, xValue, yValue, parent=None):
        super().__init__(parent)
        self.xValue = xValue
        self.yValue = yValue
        self.signals = testThreadSignals()

    def run(self):
        self.batchCounter = 0
        for x in range(int(self.xValue)):  # For loop to iterate througeach batch
            pass
            for y in range(
                int(self.yValue)):  # For loop to iterate through each image in each batch
                time.sleep(.1)
            QProcess.startDetached(os.path.dirname(os.path.realpath(__file__)) + r"\test.bat")  # Runs test.bat
            self.batchCounter += 1 #Counts the successful number *.txt files written

    @pyqtSlot(int)
    def stop(self):
        self.terminate()
        self.threadactive = False
        self.wait()
        self.signals.batchesSubmitted.emit(self.batchCounter)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

test.bat:

@ECHO OFF
ECHO Processing Batched Images.
TIMEOUT /T 15
REM write a unique text file
ECHO Process Finished.

我能够将上面的python代码毫无问题地适应我的程序。

© www.soinside.com 2019 - 2024. All rights reserved.