Skip to content Skip to sidebar Skip to footer

Stop Processing Event-queue Immediately On Qthread.exit()

I am building a Qt GUI application which uses QThread/QObject combinations to act as workers that do stuff outside the main thread. Via moveToThread, the QObject gets moved into t

Solution 1:

The Qt docs for QThread.exit are somewhat misleading:

Tells the thread's event loop to exit with a return code.

After calling this function, the thread leaves the event loop and returns from the call to QEventLoop::exec(). The QEventLoop::exec() function returns returnCode.

By convention, a returnCode of 0 means success, any non-zero value indicates an error.

Note that unlike the C library function of the same name, this function does return to the caller -- it is event processing that stops. [emphasis added]

This suggests that after calling exit(), there will be no further processing of the thread's event-queue. But that is not what happens, because QEventLoop always calls processEventsbefore checking whether it should exit. This means that the event-queue will always be empty when exec() returns.

In your example, the single-shot timer will post events to the event-queue of the receiving thread, where the connected slots will eventually be called. So no matter what you do, all those slots will be called before the thread finally quits.

A fairly simple way to work around this is to use the requestInterruption feature with a decorator that checks to see if the slot should be called:

definterruptable(slot):
    defwrapper(self, *args, **kwargs):
        ifnot self.thread.isInterruptionRequested():
            slot(self, *args, **kwargs)
    return wrapper

classWorker(ThreadedWorkerBase):
    test_signal = QtCore.pyqtSignal(str)   # just for demo    @interruptabledefdo_work(self):
        print("starting to work")
        for i inrange(10):
            print("working:", i)
            time.sleep(0.2)

    @interruptabledeferror(self):
        print("Throwing error")
        raise Exception("This is an Exception which should stop the worker thread's event loop.")

defexcepthook(type, value, traceback):
    sys.__excepthook__(type, value, traceback)
    thread = QtCore.QThread.currentThread()
    ifisinstance(thread.parent(), ThreadedWorkerBase):
        print("This is a Worker thread. Exiting...")
        thread.requestInterruption()
        thread.exit()
sys.excepthook = excepthook

Post a Comment for "Stop Processing Event-queue Immediately On Qthread.exit()"