-1

I am trying to run Multithread using PYQT5 & Qthread

I have two pushbutton associated to threads (progressbar & one action waiting for 1 sec and then print "done") that are working perfectly as they are declared within the same Class.

I do have a third PushButton that I link to an action inserted within another Class. This one makes my program crash wihtout any log message. What exactly makes the program crash is the line "self.thread2.start()".

I do not understand why this is not working! can you help me undertsand the issue?

Thanks in advance

import sys
from PyQt5.QtCore  import *
from thread_progressbar import *
from Test_MT import *


class SimulationUi(QtWidgets.QDialog):
    def __init__(self):
        super(SimulationUi, self).__init__()
        self.btnStart = QtWidgets.QPushButton('Start')
        self.btnStart2 = QtWidgets.QPushButton('Start')
        self.btnStop = QtWidgets.QPushButton('Stop')
        self.btnStop2 = QtWidgets.QPushButton('Stop')
        self.btnQuit = QtWidgets.QPushButton('Quit')

        self.myprogressbar = QtWidgets.QProgressBar()
        self.myprogressbar2 = QtWidgets.QProgressBar()

        self.grid = QtWidgets.QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.btnStart,1,0)
        self.grid.addWidget(self.btnStop,1,1)
        self.grid.addWidget(self.myprogressbar,2,0,1,3)
        self.grid.addWidget(self.btnStart2, 3, 0)
        self.grid.addWidget(self.btnStop2, 3, 1)
        self.setLayout(self.grid)

        # ------------------------
        #MULTI-THREAD MANAGEMENT
        #------------------------
        self.thread = QThread()
        self.thread.start()
        self.worker = thread_progressbar()
        self.worker.moveToThread(self.thread)
        self.worker.setValue.connect(self.myprogressbar.setValue)
        self.btnStart.clicked.connect(self.worker.startpgbar)
        self.btnStop.clicked.connect(lambda: self.worker.stoppgbar())

        class_tst = MakeList()
        class_tst.define_thread(self.btnStart2)

        self.thread3 = QThread()
        self.thread3.start()
        self.worker3 = Test()
        self.worker3.moveToThread( self.thread3 )
        self.btnStop2.clicked.connect( self.worker3.MT )


    def stop_thread(self):
        self.worker.stop()
        self.thread.quit()
        self.thread.wait()

    def quit_application(self):
        self.close()


class MakeList():
    def __init__(self):
        super(MakeList, self).__init__()
    def define_thread(self, MyObject):
        self.thread2 = QThread()
        self.thread2.start()
        self.worker2 = Test()
        self.worker2.moveToThread(self.thread2 )
        MyObject.clicked.connect( self.worker2.MT )


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    simul = SimulationUi()
    simul.show()
    sys.exit(app.exec_())

  • Test_MT file
import os, time
from PyQt5 import QtCore


class Test(QtCore.QObject):
    def MT(self):
        time.sleep(1)
        print("done")
Pat130614
  • 1
  • 1
  • It's hard to really tell the difference, as your code is missing some parts (for instance, where is `thread_progressbar`?) and it is generally a bit confusing (you move objects to that thread that's already started, your naming is not really verbose and consistent). That said, without a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), we can only *guess*. And my guess is that `Makelist` is a local variable and gets out of scope, which causes the crash due to the thread being destroyed while running. But, as said, it's just a guess. Provide a MRE. – musicamante Mar 28 '21 at 10:04

1 Answers1

0

Since the only reference to the MakeList instance in SimulationUi.__init__, is the local variable class_tst, this object together with it's attributes will be garbage collected when SimulationUi.__init__ returns. Since one of its attributes is a running thread (class_tst.thread2), this causes the program to crash. Easiest way around this is to make a persistent reference the MakeList object by assigning it to an instance variable of SimulationUi rather than to a local variable (i.e. use self.class_tst = MakeList() instead of class_tst=MakeList() in SimulationUi.__init__).

Heike
  • 24,102
  • 2
  • 31
  • 45