The thread and MyClass
instances both live in the same thread - likely the main thread:
MyClass::MyClass() {
...
Q_ASSERT(this->thread() == thread.thread());
Yet the events you're queuing to the worker object go to the worker thread:
worker.moveToThread(&thread);
Q_ASSERT(worker.thread() == &thread);
Q_ASSERT(worker.thread() != thread.thread());
The queued connection is precisely the wrong thing to do because as soon as you wait on the worker thread, the main thread's event loop won't run and won't issue any more events to the thread. The quit
call will never be delivered, since it's delivered in the main thread, but the main thread is blocked.
Instead, take the advantage of quit
being a thread-safe method. Call it from the worker thread itself:
// vvvvvvv thread context object for the call
connect(this, &MyClass::signalFinish, &worker, [this]{ thread.quit(); });
// the `quit()` will execute in `worker.thread()`
Note that the thread context object is an object whose thread()
the call will be executed in. It should not be a QThread
instance, in most cases!
When the signalFinish
is emitted, a QMetaCallEvent
carrying the functor above will be queued in the worker thread's queue, and will get executed after any existing call (and other) events are processed first.
Since you're calling finish
in the main thread, you probably don't want to wait on the thread since that will block the GUI and make your application unresponsive.
As it seems you're submitting job items to a worker thread, you might be better served by QtConcurrent::run
that submits job items to a thread pool, and does all the thread management for you. See this answer for a complete example. See this answer and that answer for some related tidbits.