Home > Software engineering >  Creating multiple QThreads and perform action AFTER all QThreads are closed
Creating multiple QThreads and perform action AFTER all QThreads are closed

Time:07-02

here I have a simple GUI. With the creation of this GUI I am starting a thread (THREAD1) which is running while the GUI is running. The task of this thread (THREAD1) is, to perform a specific action in a specific interval.

It is important, that this specific action is performed as fast as possible. So I am creating new thread objects. This is accomplished by THREAD1

Until here everything is working fine. I get the THREAD1 to work. I am also able to get threads created by THREAD1 to work.

here the code.

from PyQt6.QtCore import QThread, QObject
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget
import time


class GetMarketDataV2(QThread):

    def __init__(self, index):
        super(GetMarketDataV2, self).__init__()
        self.index = index

    def run(self):

        time.sleep(5)
        print(f"Thread: {self.index}\n")


class DataCollectionLoop(QObject):
    """
    Runs as long as the GUI is running. Terminated with the Main window close event.
    The task of this class is, to start a specific amount of threads with a specific interval.
    """
    def __init__(self):
        super(DataCollectionLoop, self).__init__()
        self.thread = {}
        self.first_startup = True

    def run(self):

        while True:
            # In this example 10 threads are created.
            for i in range(10):
                self.thread[i] = GetMarketDataV2(index=i)
                self.thread[i].start()

            # I want this line below to execute after all threads above are done with their job.
            print("print this statement after all threads are finished")

            # Here the specific interval is 10 seconds.
            time.sleep(10)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Setting up thread which controls the data collection.
        self.thread = QThread()

        # Instantiating the DataCollectionLoop object and moving it to a thread.
        data_collection = DataCollectionLoop()
        data_collection.moveToThread(self.thread)

        # calling the run method when the thread is started.
        self.thread.started.connect(data_collection.run)

        # Starting the thread
        self.thread.start()

        # Minimal GUI
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        self.show()

    # Terminating the thread when window is closed.
    def closeEvent(self, event):
        self.thread.terminate()


app = QApplication([])
window = MainWindow()

I have searched a decent amount of time, but couldn't find a solution to my problem.

Which is:

I want to wait for all threads, which are created by THREAD1, to finish, before continuing with my code.

I think I should catch the states of each thread (if they are finished or not) but I don't know exactly how..

Thank you very much!

CodePudding user response:

As @musicamante suggested I got the desired result using the isFinished() method.

Here is how I made it:

# Waits for all threads to finnish. Breaks out of the loop afterwards
    while True:
        for thread in self.thread.values():
            if not thread.isFinished():
                break
        else:
            break

Another solution I stumpled uppon which does the trick for me, is to work with QRunnables and a Threadpool.

for market in forex_markets:

    market = GetMarketData()  # Subclassed QRunnable
    self.threadpool.start(market)

self.threadpool.waitForDone()

Thank you!

  • Related