Почему этот qthread pyqt5 запускается только один раз каждые два нажатия кнопки?

У меня есть программа, которую я хочу при нажатии кнопки создать qthread и запустить некоторый набор кода. В конце я хочу, чтобы основной поток уничтожил рабочий поток.

Следующий код показывает одну из моих попыток. Из того, что я могу сказать, он создает поток только при первом нажатии кнопки, а при втором нажатии он уничтожает предыдущий поток и создает и запускает функцию work(). Если вы долго ждете между нажатиями кнопок, вы получаете вид, похожий на первый щелчок кнопки, что он не запускает функцию work(). Может ли кто-нибудь увидеть что-то, что я делаю неправильно. У меня есть более сложный пример, который я пытаюсь разбить на меньшую часть (Pyqt5 qthread + сигнал не работает + зависание графического интерфейса)

Код:

import time
import sys

from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QPushButton, QTextEdit, QVBoxLayout, QWidget


class Worker(QObject):
    """
    Must derive from QObject in order to emit signals, connect slots to other signals, and operate in a QThread.
    """
    sigDone = pyqtSignal(int)

    def __init__(self, id: int):
        print("Here 11")
        super().__init__()
        print("Here 9")
        self.__id = id

    @pyqtSlot()
    def work(self):
      print("Here 10")
      for count in range(20):
          print("ID: " + str(self.__id) + ", Count: " + str(count))
          time.sleep(0.1)
          app.processEvents()  # this could cause change to self.__abort
      self.sigDone.emit(self.__id)
      #Need a done signal.          

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()
        print("Here 1")
        self.setWindowTitle("Thread Example")
        form_layout = QVBoxLayout()
        self.setLayout(form_layout)
        self.resize(400, 400)
        print("Here 2")
        self.btnStartWorker = QPushButton()
        self.btnStartWorker.clicked.connect(self.start_worker)
        self.btnStartWorker.setText("Start Worker")
        form_layout.addWidget(self.btnStartWorker)

        self.__threads = None

    def start_worker(self):
        print("Here 3")
        worker = Worker(999)
        thread = QThread()
        print("Here 4")
        self.__threads = []
        self.__threads.append(thread)
        print("Here 5")
        worker.moveToThread(thread)
        worker.sigDone.connect(self.workerDone)
        print("Here 6")
        thread.started.connect(worker.work)
        print("Here 7")
        thread.start()
        print("Here 8")    

    @pyqtSlot(int)
    def workerDone(self, threadNumber):
        print("Here 12")
        print("Thread " + str(threadNumber) + " is done.")
        for thread in self.__threads:
            thread.quit()
            thread.wait()
        print("Here 13")

if __name__ == "__main__":
    app = QApplication([])

    form = MyWidget()
    form.show()

    sys.exit(app.exec_())

Результаты нескольких нажатий кнопок:

E:\myCode\python\pyQt>python3 pyQtv6.py
Here 1
Here 2
Here 3
Here 11
Here 9
Here 4
Here 5
Here 6
Here 7
Here 8
Here 3
Here 11
Here 9
Here 4
QThread: Destroyed while thread is still running
Here 5
Here 6
Here 7
Here 8
Here 10
ID: 999, Count: 0
ID: 999, Count: 1
ID: 999, Count: 2
ID: 999, Count: 3
ID: 999, Count: 4
ID: 999, Count: 5
ID: 999, Count: 6
ID: 999, Count: 7
ID: 999, Count: 8
ID: 999, Count: 9
ID: 999, Count: 10
ID: 999, Count: 11
ID: 999, Count: 12
ID: 999, Count: 13
ID: 999, Count: 14
ID: 999, Count: 15
ID: 999, Count: 16
ID: 999, Count: 17
ID: 999, Count: 18
ID: 999, Count: 19
Here 12
Thread 999 is done.
Here 13
Here 3
Here 11
Here 9
Here 4
Here 5
Here 6
Here 7
Here 8
Here 3
Here 11
Here 9
Here 4
QThread: Destroyed while thread is still running
Here 5
Here 6
Here 7
Here 8

person NDEthos    schedule 28.03.2018    source источник
comment
Не могли бы вы объяснить, в чем проблема? test меняет worker на self.worker, локальные переменные уничтожаются, когда функция завершает выполнение, в случае потока он не уничтожается, так как вы сохраняете его в списке, но worker удаляется.   -  person eyllanesc    schedule 28.03.2018
comment
Кажется, вы меня к чему-то подтолкнули. Пример, на который я ссылался, сохраняет поток и рабочий объект в виде кортежа. Я только сохранил поток, чтобы он не был собран мусором. У меня все еще есть некоторые другие ошибки, когда я меняю self.__threads.append(thread) на self.__threads.append((thread, worker)) но это те, которые я могу исправить. Спасибо. О, проблема была в том, что при первом нажатии вы получаете только 1,2,3,11,9,4,5,6,7,8 для печати, именно в таком порядке. Затем при втором щелчке вы получаете подсчет для печати, от 0 до 19. Если вы долго ждете между нажатиями кнопок, вы снова получаете последовательность от 1 до 8.   -  person NDEthos    schedule 28.03.2018
comment
У вас все еще есть проблемы с изменениями? Если да, объясните, в чем ваша текущая проблема.   -  person eyllanesc    schedule 28.03.2018
comment
Объект 'tuple' не имеет атрибута 'quit', но, как я уже сказал, у меня есть это. Это только проблема доступа, потому что она превратилась из списка потоков в список кортежей.   -  person NDEthos    schedule 28.03.2018