I have a program that I want to, on button click, create a qthread and run some set of code. At the end I want the main thread to destroy the worker thread.
The following code shows one of my attempts. From what I can tell it only creates the thread on the first button click and on the second click it destroys the previous thread and creates and runs the work() function. If you wait to long in between button clicks you get the appearance like the first button click, that it does not run the work() function. Can anyone see something that I am doing wrong. I have a more complex example form someone else that I am trying to break down into a smaller part.( Pyqt5 qthread + signal not working + gui freeze )
Code:
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_())
Results from some button clicks:
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