QThread testThr;
QObject* testObj = new QObject;
testObj->moveToThread(&testThr);
connect(&testThr, &QThread::started, [&]
{
// Do something
});
//connect(&testThr, &QThread::finished, testObj, &QObject::deleteLater);
testThr.start();
// Do something
testThr.quit();
testThr.wait();
// Do something with testObj
delete testObj; // Is this OK?
I create a new QObject
and move it to the newly created thread, but I still need this object after its thread is finished. Thus, I don't want to destroy it in its newly assigned thread, so the common approach with QObject::deleteLater
won't fit here.
The question is, would it be fine to delete it after its thread is finished and no dataraces with its event loop are going to happen?
it won't crash the application, because Qt currently tracks each thread data with reference counting, so everything will survive until the object is destroyed, however ..... the docs discourage this.
You must ensure that all objects created in a thread are deleted before you delete the QThread. This can be done easily by creating the objects on the stack in your run() implementation.
and
Calling delete on a QObject from a thread other than the one that owns the object (or accessing the object in other ways) is unsafe, unless you guarantee that the object isn't processing events at that moment.
If no event loop is running, events won't be delivered to the object. For example, if you create a QTimer object in a thread but never call exec(), the QTimer will never emit its timeout() signal. Calling deleteLater() won't work either. (These restrictions apply to the main thread as well.)
The problematic part about destroying it in another thread after the owning thread is destroyed is the destroyed()
signal. since it is emitted on a different thread then it must be sent to the eventloop, which is no-longer running, and so the attached handlers on the same thread will be missed, this could be problematic depending on the object and the importance of the attached slots, and will generally lead to weird behavior.
you can move it to another thread when the thread is finished()
to make sure that the destroyed()
slots will run.