Как запускать QThread в цикле?

Для начала я создаю два класса-QThread:

  • Worker - таймер,
  • Worker2 - выводит вопросы.

Затем создаю их переменные в MainGame и пытаюсь запустить циклом определенное количество раз:
первый раз, затем, когда кончился, - снова, и так далее.

Но программа все время вылетает, не желая ждать, пока кончится QThread, или же она запустит все Треды разом и будет ждать, пока они все (штук 10 вместо 2) разом закончатся.

Надеюсь, что хоть что-то понятно.

import time
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import *
from random import choice


class Worker(QObject):
    end = pyqtSignal()

    def __init__(self, sec):
        super().__init__()
        self.seconds = sec

    @pyqtSlot()
    def run(self):
        print(self.seconds)
        time.sleep(1)
        for i in range(self.seconds):
            self.seconds -= 1
            print(self.seconds)
            time.sleep(1)
        self.end.emit()


class Worker2(QObject):
    stop = True

    def __init__(self, pl_list):
        super().__init__()
        self.pl_list = pl_list

    @pyqtSlot()
    def run(self):
        while self.stop is True:
            time.sleep(3)
            print(choice(self.pl_list), 'вопрос')


class MainGame(QMainWindow):
    def __init__(self):
        super().__init__()
        self.timer_n_quests()

    def timer_n_quests(self):
        self.thr2 = QThread()
        self.worker2 = Worker2(['Саша', 'Маша', 'Паша', 'Даша'])
        self.worker2.moveToThread(self.thr2)
        self.thr2.started.connect(self.worker2.run)
        self.thr2.finished.connect(self.thr2.quit)

        self.thr = QThread()
        self.worker = Worker(12)
        self.worker.moveToThread(self.thr)
        self.worker.end.connect(self.close)
        self.thr.finished.connect(self.thr.quit)
        self.thr.started.connect(self.worker.run)

        for i in range(7):
            self.thr.start()
            self.thr2.start()
            print(i + 1, 'round')

    def stopW2(self):
        Worker2.stop = False

    def printed(self, st):
        print(st)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainGame()
    ex.show()
    sys.exit(app.exec())

Ответы (1 шт):

Автор решения: S. Nick

Я не уверен, что правильно понял вас, но попробовал что-то сделать для вас.

import sys
import time
from random import choice
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *


class Worker(QObject):
    end = pyqtSignal()

    def __init__(self, sec):
        super().__init__()
        self.seconds = sec

    @pyqtSlot()
    def run(self):
# ?        time.sleep(1)
        #print()
        for i in range(self.seconds):
            self.seconds -= 1
            #print(f'{self.seconds:>2} сек.')
            time.sleep(1)
        self.end.emit()


class Worker2(QObject):
    stop = True
    questionSignal = pyqtSignal(str)                                   # +++

    def __init__(self, pl_list):
        super().__init__()
        self.pl_list = pl_list

    @pyqtSlot()
    def run(self):
#        while self.stop is True:
        self.stop = True
        while self.stop:                                               # +++
# ?          time.sleep(3)                                             # ?
            question = choice(self.pl_list)
            #print(question, 'вопрос')
            self.questionSignal.emit(question)                         # +++
            time.sleep(3)                                              # +


class MainGame(QMainWindow):
    def __init__(self):
        super().__init__()
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        self.centralwidget = QWidget()
        self.setCentralWidget(self.centralwidget)
        
        self.textBrowser = QtWidgets.QTextBrowser()
        
        layout = QGridLayout(self.centralwidget)        
        layout.addWidget(self.textBrowser) 
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self.timer_n_quests()

    def timer_n_quests(self):
        self.thr2 = QThread()
        self.worker2 = Worker2(['Саша', 'Маша', 'Паша', 'Даша'])
        self.worker2.moveToThread(self.thr2)
        self.thr2.started.connect(self.worker2.run)
#        self.thr2.finished.connect(self.thr2.quit)
        self.worker2.questionSignal.connect(self.question_signal)      # +++

# Worker  - таймер
        self.thr = QThread()
        self.worker = Worker(12)
        self.worker.moveToThread(self.thr)
        
#        self.worker.end.connect(self.close)
#        self.thr.finished.connect((self.thr.quit)                     # ???
        self.worker.end.connect(self.close_worker)                     # +++
        
        self.thr.started.connect(self.worker.run)
        
        self.number_of_times = 7                                       # +++
        self.one_cycle()                                               # +++
        
    def one_cycle(self):                                               # +++
#        for i in range(7):                                   
        self.thr.start()
        self.thr2.start()
        self.textBrowser.append(f'{8 - self.number_of_times} round')   # +++

# +++ vv           
    def close_worker(self):            
        self.worker2.stop = False
        self.thr2.terminate()
        self.thr2.wait()        
        self.thr.terminate()

        self.number_of_times -= 1
        if self.number_of_times:
            self.worker.seconds = 12
            self.one_cycle()
        else:
            self.worker2.stop = False
            self.worker.seconds = 0
            self.thr2.terminate()
            self.thr2.quit()
            self.thr2.deleteLater()
            self.thr2.wait()
            self.thr.terminate()
            self.thr.deleteLater()
            
            self.textBrowser.append(f'Finish: ========================')

    def question_signal(self, question):
        if self.worker2.stop and self.worker.seconds:
            self.textBrowser.append(f'\t{question} -> {self.worker.seconds} сек.')  
        

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainGame()
    ex.resize(300, 400)
    ex.show()
    sys.exit(app.exec())

введите сюда описание изображения

→ Ссылка