Search code examples
python-3.xpyqt5qthread

Stop a Qthread PyQt5


I've tried several methods to stop a Qthread, but none seem to work. When I look at the Call Stack, the thread has not ended, and while click again, another thread starts, thus getting infinite active threads and consuming more unnecessary memory. I tried to put terminate() and quit() and nothing stops the thread. So I also tried all of them together and no result

from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import QThread
from PyQt5 import QtWidgets
from PyQt5 import QtCore
import time
import sys

class MyThread(QThread):
    def run(self):
        x=0
        print("Starting...")
        while x<5:
            time.sleep(1.5)
            print("Running...")
            x=x+1

    def close(self):
        self.isRunning=False
        self.terminate()
        self.wait()
        self.quit()
        self.wait()
        print("Done")

class Ui_MainWindow(QMainWindow):
     def __init__(self):
         super(Ui_MainWindow, self).__init__()
         self.btn = QtWidgets.QPushButton(self)
         self.btn.setGeometry(QtCore.QRect(77, 30, 50, 30))
         self.btn.setText("CLICK")
         self.btn.clicked.connect(self.doSomething)


     def doSomething(self,event):
         self.worker=MyThread()
         self.worker.setTerminationEnabled(True)
         self.worker.finished.connect(self.worker.close)
         self.worker.start() 

if __name__ == "__main__":
    app = QApplication([])
    ui = Ui_MainWindow()
    ui.show()
    sys.exit(app.exec_())

enter image description here


Solution

  • I managed to solve my problem using threading native library and with pyqtSignal. When clicking on the button, it loses its connection and starts the thread. After the end of the loop in the thread, a signal is issued and thus returning the connection to the button. This way, it prevents the user from clicking the button several times.

    from PyQt5.QtWidgets import QMainWindow, QApplication
    from PyQt5.QtCore import pyqtSignal
    from PyQt5 import QtWidgets
    from PyQt5 import QtCore
    import time
    import sys
    import threading
    
    class Ui_MainWindow(QMainWindow):
         signal=pyqtSignal(str)
         def __init__(self):
             super(Ui_MainWindow, self).__init__()
             self.btn = QtWidgets.QPushButton(self)
             self.btn.setGeometry(QtCore.QRect(77, 30, 50, 30))
             self.btn.setText("CLICK")
             self.signal.connect(self.signalResponse)
             self.btn.clicked.connect(self.doSomething)
    
         def doSomething(self,event):
             print("Starting...")
             self.btn.disconnect()
             worker=threading.Thread(target=self.worker)
             worker.start()
    
         def signalResponse(self,response):
             if response=="Finished":
                self.btn.clicked.connect(self.doSomething)
                print(response)
    
         def worker(self):
            x=0
            while x<5:
                time.sleep(0.5)
                print("Running...")
                x=x+1
            self.signal.emit("Finished")
    
    if __name__ == "__main__":
        app = QApplication([])
        ui = Ui_MainWindow()
        ui.show()
        sys.exit(app.exec_())