0

I'm attempting to run a CPU intensive task in a separate QThread using PyQt5. I've tried several permutations of the code, only to get one of 2 unwanted results.

Either this error: "QThread: Destroyed while thread is still running"

Or the GUI hangs as if the separate thread doesn't exist!

I've created a basic example. How do I get it to work like I expect?

Most importantly, I want to run the QThread based on whether a condition is True or not. If it's True, show a warning that lets the user cancel the operation. If False, just run the thread.

Here's the code:

from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QVBoxLayout, QHBoxLayout, QMessageBox
from PyQt5.QtCore import QThread, QObject

class createMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setFixedSize(300, 100)
        self.setWindowTitle('Thread testing')
        self.show()


class createMainWidget(QWidget):
    def __init__(self):
        super().__init__()

        threadButton = QPushButton('Start thread!')
        threadButton.clicked.connect(self.startThread)

        layout = QVBoxLayout(self)
        layout.addWidget(threadButton)


    def startThread(self):
        thread = QThread()
        worker = createWorker()
        worker.moveToThread(thread)
        thread.started.connect(worker.run) # It's like this is invisible. It should work.

        # I want to display a warning message if a certain condition is met. If the warning is displayed, the user has the option of not continuing.
        displayMessage = True
        if displayMessage == True:
            warningMessage = QMessageBox()
            warningMessage.setIcon(QMessageBox.Warning)
            warningMessage.setWindowTitle('Warning')
            warningMessage.setText('Be warned!')
            warningMessage.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
            warningMessage.accepted.connect(thread.start) # Why does this destroy the QThread straight away???
            warningMessage.exec_()

        # The condition is false, therefore just start the thread.
        elif displayMessage == False:
            thread.start() # This destroys the QThread as well. Why?



class createWorker(QObject):
    def __init__(self):
        super().__init__()

    def run(self):
        print('Secondary thread working')
        i = 0
        while i < 1000000000: i += 1 # Simulate CPU intensive activity
        print('Done')


app = QApplication([])

mainWidget = createMainWidget()
mainWindow = createMainWindow()
mainWindow.setCentralWidget(mainWidget)

app.exec_()


  • @eyllanesc That doesn't help I'm afraid, please could you re-open my question? – Josh Brenner Jun 27 '20 at 16:52
  • 1) use `thread = QThread(self)` and `self.worker = createWorker()` – eyllanesc Jun 27 '20 at 17:04
  • Yes already tried that and it doesn't work. It just does nothing. It throws no error, but it doesn't run the code properly either. The run() method in createWorker is completely ignored, apparently. – Josh Brenner Jun 27 '20 at 17:07
  • Please excuse me, that actually did work. Apologies. Why does it need to be self.worker? Out of curiosity – Josh Brenner Jun 27 '20 at 17:08
  • Did you read the answer from the duplicate? the keyword is: scope, each variable is destroyed when the scope ends, and that's what happens in your case. Not only copy-paste code but you must analyze the explanation. – eyllanesc Jun 27 '20 at 17:10
  • I did yes, but no mention of scope. There wasn't much to analyse in your previous answer to the other question, but I appreciate you taking the time now. – Josh Brenner Jun 27 '20 at 17:17

0 Answers0