icolumbro
icolumbro

Reputation: 123

PySide6 and QThread: how to not overlap two different threads?

I'm writing a GUI app using PySide6 and QThread. I've two different QThread objects that run two long time run jobs, they can't overlap so if one thread is running, the second must wait until the first ends, how can obtain this?

I try to write a simple code example:

from PySide6.QtCore import QThread
from MyJobs import LongJob

job_a = LongJob()
job_b = LongJob()

thread_a = QThread()
thread_b = QThread()

job_a.moveToThread(thread_a)
job_b.moveToThread(thread_b)

thread_a.start()
thread_b.start() # if thread_a is running, thread_b must wait until thread_a ends, then run and viceversa

Upvotes: 0

Views: 1855

Answers (1)

eyllanesc
eyllanesc

Reputation: 244291

Threads are workspaces and you instead want to manage how jobs are executed. In that case, task B must be managed to execute when task A finishes, and vice versa using signals.

import random
import time

from PySide6.QtCore import QCoreApplication, QObject, QThread, QTimer, Qt, Signal, Slot


class LongJob(QObject):
    started = Signal()
    finished = Signal()

    @Slot()
    def run_task(self):
        assert QThread.currentThread() != QCoreApplication.instance().thread()
        self.started.emit()
        self.long_task()
        self.finished.emit()

    def long_task(self):
        t = random.randint(4, 10)
        print(f'identifier: {self.property("identifier")}, delay: {t} seconds')
        for i in range(t):
            time.sleep(1)
            print(f"{i+1} seconds")


if __name__ == "__main__":
    import sys

    app = QCoreApplication(sys.argv)

    job_a = LongJob()
    job_a.setProperty("identifier", "job_a")
    job_b = LongJob()
    job_b.setProperty("identifier", "job_b")

    thread_a = QThread()
    thread_a.start()
    job_a.moveToThread(thread_a)

    thread_b = QThread()
    thread_b.start()
    job_b.moveToThread(thread_b)

    job_a.finished.connect(job_b.run_task, Qt.QueuedConnection)
    job_b.finished.connect(job_a.run_task, Qt.QueuedConnection)

    # start task
    QTimer.singleShot(0, job_a.run_task)

    sys.exit(app.exec())

Upvotes: 2

Related Questions