How to properly terminate a QThread from a GUI application?

15,158

From the Qt documentation for QThread::terminate:

Warning: This function is dangerous and its use is discouraged. The thread can be terminated at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to clean up after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.

It's probably a much better idea to re-think your threading strategy such that you can e.g. use QThread::quit() to signal the thread to quit cleanly, rather than trying to get the thread to terminate this way. Actually calling thread.exit() from within the thread should do that depending on how you have implemented run(). If you'd like to share the code for your thread run method that might hint as to why it doesn't work.

Share:
15,158
Bo Milanovich
Author by

Bo Milanovich

I mostly deal with Python and its Qt bindings (PyQt and PySide for the most part) and web frameworks, but you'll see me poking around JavaScript, C#, and ASP.NET forums as well. Check out my Pluralsight course on developing desktop applications using Python and Qt - http://www.pluralsight.com/courses/python-desktop-application-development

Updated on June 25, 2022

Comments

  • Bo Milanovich
    Bo Milanovich about 2 years

    I tried using self.terminate() in the QThread class, and also self.thread.terminate() in the GUI class. I also tried putting self.wait() in both cases. However, there are two scenarios that happen:

    1) The thread does not terminate at all, and the GUI freezes waiting for the thread to finish. Once the thread finished, the GUI unfreezes and everything is back to normal.

    2) The thread indeed does terminate, but at the same time it freezes the entire application.

    I also tried using self.thread.exit(). No joy.

    To further clarify, I am trying to implement a user-abort button in GUI which would terminate the executing of the thread at any point in time.

    Thanks in advance.

    EDIT:

    Here is the run() method:

    def run(self):
        if self.create:
            print "calling create f"
            self.emit(SIGNAL("disableCreate(bool)"))
            self.create(self.password, self.email)
            self.stop()            
            self.emit(SIGNAL("finished(bool)"), self.completed)
    
    def stop(self):
         #Tried the following, one by one (and all together too, I was desperate):
         self.terminate()
         self.quit()
         self.exit()
         self.stopped = True
         self.terminated = True
         #Neither works
    

    And here is the GUI class' method for aborting the thread:

    def on_abort_clicked(self):
         self.thread = threadmodule.Thread()
         #Tried the following, also one by one and altogether:
         self.thread.exit()
         self.thread.wait()
         self.thread.quit()
         self.thread.terminate()
         #Again, none work
    
  • docsteer
    docsteer over 12 years
    Hmm. And I assume the self.create() method is the time-consuming method in the thread? Generally what you would do in there is something like while not self.terminated() { do slow operation parts.. }. Unfortunately I don't know Python well, but looks like there is a threading tutorial here that might help
  • Bo Milanovich
    Bo Milanovich over 12 years
    I tried that as well. It happened to work somewhat (the GUI wouldn't freeze, but the thread would not terminate either). However the oddest thing just happened. I deleted all the def stop(self) code in the thread and the def on_abort_clicked(self) code in the GUI, and rewrote it. I simply put self.terminate() in the thread's stop() function and did self.thread.stop() in the GUI class. It works like a charm. AFAIK, that's the first thing I tried, and it didn't work before. I probably missed something.