Let\'s say I call QtConcurrent::run()
which runs a function in a worker thread, and in that function I dynamically allocate several QObjects (for later use). Since
QThread
is not documented to automatically move any QObject
s when it finishes, so I think we can already conclude that it does no such thing. Such behavior would be very surprising, and at odds with the rest of the API.
Just for completeness, I tested with Qt 5.6:
QObject o;
{
QThread t;
o.moveToThread(&t);
for (int i = 0; i < 2; ++i)
{
t.start();
QVERIFY(t.isRunning());
QVERIFY(o.thread() == &t);
t.quit();
t.wait();
QVERIFY(t.isFinished());
QVERIFY(o.thread() == &t);
}
}
QVERIFY(o.thread() == nullptr);
Recall that a QThread
is not a thread, it manages a thread.
When a QThread
finishes, it continues to exist, and the objects that live in it continue to live in it, but they no longer process events. The QThread
can be restarted (not recommended), at which point event processing will resume (so the same QThread
could then be managing a different thread).
When a QThread
is destroyed, the objects that lived in it cease to have any thread affinity. The documentation doesn't guarantee this, and in fact says "You must ensure that all objects created in a thread are deleted before you delete the QThread
."
Let's say I call
QtConcurrent::run()
which runs a function in a worker thread, and in that function I dynamically allocate several QObjects (for later use). Since they were created in the worker thread, their thread affinity should be that of the worker thread. However, once the worker thread terminates, the QObject thread affinity should no longer be valid.
The QThread
does not terminate in this scenario. When a task spawned by QtConcurrent::run
finishes, the QThread
it was running in is returned to the QThreadPool
and may be reused by a subsequent call to QtConcurrent::run
, and QObject
s living in that QThread
continue to live there.
QThreadPool::globalInstance()->setMaxThreadCount(1);
QObject *o = nullptr;
QThread *t = nullptr;
QFuture f = QtConcurrent::run([&] {
o = new QObject;
t = o->thread();
QVERIFY(t == QThread::currentThread());
});
f.waitForFinished();
QVERIFY(t == o->thread());
QVERIFY(t->isRunning());
f = QtConcurrent::run([=] {
QVERIFY(t == QThread::currentThread());
});
f.waitForFinished();
You might want to manually move an object out of a QThread
before it is returned to the QThreadPool
, or just don't use QtConcurrent::run
. Having a QtConcurrent::run
task construct QObject
s which outlive the task is a questionable design, tasks should be self-contained. As noted by @Mike, the QThread
s used by QtConcurrent::run
do not have event loops.