0

I'm a PyQt5 newbie. I've written the following code which should ideally terminate.

from PyQt5.QtCore import QCoreApplication, pyqtSignal, QObject
import sys
import thread

class MainWindow(QObject):    
    def __init__(self):
        super().__init__()
        self.myMethod()        

    def myMethod(self):
        self.myThread = thread.MainWindow(self)
        self.myThread.threadTerminate.connect(self.finished)
        self.myThread.start()

    def finished(self, arg1):
        print("Message recieved is "+arg1)
        QCoreApplication.quit()

if __name__ == '__main__':    
    qApp = QCoreApplication(sys.argv)
    w = MainWindow()
    qApp.exec_()

The thread code is:

from PyQt5.QtCore import QThread, QCoreApplication, pyqtSignal
import sys
import time

class MainWindow(QThread):
    threadTerminate = pyqtSignal(bool)
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.itsOver = False

    def run(self):
        print("Hello World!")
        time.sleep(3)
        print("Alice")
        time.sleep(4)
        print("Bob")
        time.sleep(4)
        self.stop()

    def stop(self):
        print("About to terminate....")
        self.itsOver = True
        self.threadTerminate.emit(self.itsOver)
        self.terminate()  

What am I doing wrong? Is there any way to trace the execution flow of my program and know the state of my variables?

user1801060
  • 2,733
  • 6
  • 25
  • 44

1 Answers1

1

Seems like you have a simple race condition.

When I add a time.sleep(1) between the call to self.threadTerminate.emit and self.terminate, the program finishes as expected (except for your print statement where str and bool cant be concatenated, naturally).

Without knowing the exact details of how Qt processes the signal/slot flow, I'd say that your call to terminate clears up the thread and its signals before the invocation of the connected slot in the MainWindow's thread, thereby erasing the finished event from the event loop and skipping your call to Quit().

In short: Do a self.exit() in the QThread instead. It's the graceful shutdown alternative to terminate, which as far as I've seen you should avoid whenever possible.


As a side note, maybe rethink your module and class namings. The thread module was a module in Python2, renamed to _thread in Python3. That confused me at first (same as the commenters above) since you have an own module called "thread.py". Furthermore, MainWindow resembles the name of PyQt5.QtWidgets.QMainWindow, while a QCoreApplication doesn't have "windows".

Jeronimo
  • 2,268
  • 2
  • 13
  • 28