1

This question is related to my previous one

Problem occurs where I'm switching between Alpha to Gamma items too fast. The run() method of GenericThread cannot complete it's loop without error since information given to it changes when i'm switching between items of List1

I've added exeptions but that's not the best workaround in this situation, I have to terminate the thread if it's running and then start it again, but when i'm terminating it, GUI freezez forever (BUT its not like it freeze all the time while switching between items, sometimes self.terminate() works sometimes not and freezes i cant find out why) ...

class GenericThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def stop(self):
        self.terminate()

    def __del__(self):
        self.quit()
        self.wait()

    def run(self):
        #Some very long stuff
        self.emit( QtCore.SIGNAL('itemSelectionChanged()'))
        return

class MainUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_Win()
        self.ui.setupUi(self)

        self.genericThread = GenericThread(self, listIndex=2)
        self.connect(self.genericThread, QtCore.SIGNAL("fillListWithItems(QString, int)"), self.fillListWithItems )
        self.ui.List1.list1SelectedItem.connect(self.fill_List2)
        ...

    def fill_List2(self):
        if self.genericThread.isRunning():
            self.genericThread.stop()
        self.ui.List2.clear()
        list1SelectedItem = str(self.ui.List1.currentItem().text())
        self.genericThread.start()

Now, why does GUI freez and how to termiante self.genericThread correctly ?

PYPL
  • 1,819
  • 1
  • 22
  • 45
  • Does it still crash if you re-instantiate `self.genericThread` before calling start again? – three_pineapples Jun 23 '15 at 07:28
  • @three_pineapples just tested it and Yes, its still crashing – PYPL Jun 23 '15 at 07:37
  • you have to call 'wait()' after 'stop()', terminate function is not immediate – mguijarr Jun 23 '15 at 11:03
  • @mguijarr `wait()` will wait for the `run()` to return a value which will cause only if that long function complete, i dont want to wait so long, thus it becomes useless. – PYPL Jun 23 '15 at 11:21
  • sorry, not true: after a call to "terminate()" the thread is "killed", however you have to wait for it to be really stopped it depends on OS scheduling ; did you try what I suggest? – mguijarr Jun 23 '15 at 11:31
  • @mguijarr just did it, it still waits for `run` to complete :( – PYPL Jun 23 '15 at 11:40
  • @PYPL. Stop the work, then stop the thread. If the work is being done in a loop, use a flag to break out of it. The flag can be set inside `stop()`, which must then call `quit()` and `wait()`. – ekhumoro Jun 23 '15 at 14:46
  • You can't stop the thread gracefully if it performs some long operation. You need to interrupt that operation manually using a flag. – Pavel Strakhov Jun 23 '15 at 18:27

1 Answers1

4

Based on your comments, @ekhumoro and @Pavel I've fixed my issue and now it runs as i want, well eventhought self.terminate() would be much much better if it worked.

class GenericThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.stopFlag = False

    def stop(self):
        self.stopFlag = True

    def __del__(self):
        self.quit()
        self.wait()

    def run(self):
        #Some very long stuff
            if self.stopFlag:
                self.stopFlag = False #Resetting the flag (in my case I have to do this!)
                break #Breaks main loop to finish 'run()'
            else:
                self.emit( QtCore.SIGNAL('itemSelectionChanged()'))

class MainUI(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_Win()
        self.ui.setupUi(self)

        self.genericThread = GenericThread(self, listIndex=2)
        self.connect(self.genericThread, QtCore.SIGNAL("fillListWithItems(QString, int)"), self.fillListWithItems )
        self.ui.List1.list1SelectedItem.connect(self.fill_List2)
        ...

    def fill_List2(self):
        if self.genericThread.isRunning():
            self.genericThread.stop()
        self.ui.List2.clear()
        list1SelectedItem = str(self.ui.List1.currentItem().text())
        self.genericThread.start()
PYPL
  • 1,819
  • 1
  • 22
  • 45