QThread exception management and thread race
<p>I have a GUI (PySide) application that uses QThread. I have a signal in my QThread that is emitted when an exception occurs so that I can handle the exception in the main thread. However, the rest of the function starting the thread is still executed. I tried the <code>wait</code> function to block the execution but it does not work. Here is my implementation:</p>

<p><strong>QThread daughter</strong></p>

<pre><code>class LongTaskThread(QtCore.QThread):
    task_finished = QtCore.Signal()
    task_failed = QtCore.Signal(Exception)

    def __init__(self, allow_log=True, test_mode=False, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
        self.task_failed.emit(Exception())

    def wait_with_gui_refresh(self):
        while self.isRunning():
            time.sleep(0.1)
            if not self.test_mode:
                QtGui.QApplication.processEvents()
</code></pre>

<p><strong>Main thread</strong></p>

<pre><code>def test():
   my_thread = LongTaskThread()
   my_thread.task_finished.connect(on_finished)
   my_thread.task_failed.connect(on_failed)
   my_thread.start()
   # my_thread.wait()    &lt;---- tentative 1
   # my_thread.wait_with_gui_refresh()    &lt;---- tentative 2
   print('bla bla bla bla')

def on_finished)():
   pass

def on_failed(err):
  raise err
</code></pre>

<p>I expected that the <code>print</code> would never been hit, but whether I use the <code>wait</code> function or the <code>wait_with_gui_refresh</code> function, or nothing, the print is always printed.</p>

<p>How to stop the test function when an exception is raised inside the QThread ?</p>

<p>In your <code>test</code> function, the sequence of events is this:</p>

<ol>
<li>The thread starts</li>
<li>The thread's <code>run</code> method is called</li>
<li>The <code>task_failed</code> signal is emitted <em>asynchronously</em> (i.e. it's posted to the receiver's event queue)</li>
<li>The thread's <code>run</code> method returns</li>
<li>If the thread's <code>wait</code> method is called here, it will return <code>True</code> immediately because there is nothing to wait for (i.e. <code>run</code> has already returned)</li>
<li>A message is printed, and <code>test</code> returns</li>
<li>Control returns to the event-loop, and the <code>task_failed</code> signal is processed</li>
<li>An exception is raised in <code>on_failed</code></li>
</ol>

<p>It's hard to see anything to object to here. Presumably, you don't want to block the gui whilst the worker thread is running, so it makes perfect sense to process any exceptions aynchronously. But for that to happen, control must return to the event-loop of the main thread - which means the <code>test</code> function <em>must</em> return immediately. If you want to run some code after the thread starts, connect a slot to its <code>started</code> signal.</p>

python multithreading qt exception-handling pyside