QtConcurrent and moveToThread
In my application, the whole user work session is managed by a graph of QObjects.
I have a write/read function to save/load the user work session from/to an xml file.
So, when the read function is executed, the xml file is parsed and QObjects are created to restore the user work session.
Everything works correcly... but... with a big xml file, the loading time can be long (10s-30s, also due to other ressources loading and some pre-processing), so I would like to load the file from a worker thread (so the GUI isn't freezed)
To do that, I use "QtConcurrent::run" to execute the read function, but I'm facing a problem : all QObjects created by the read function belongs to the QtConcurrent worker thread.
I tried to "moveToThread" all objects to the "QApplication::instance()->thread()" while they are created by the read function.
The problem is only partially solved. For example if we have "A" class with constructor defined as following :
p_mySocket = new QTcpSocket();
Then the read function read an "A" instance from the XML file and execute :
Found "A" instance tag
A* pA = new A();
=> the problem is about the "p_mySocket " object : it still belongs to the QtConcurrent worker thread.
=> I can't editall my classes to implement a "moveToMainThread" method which move all the class members to the main thread
So my questions are :
1/ is there anyway to move ALL objects that belongs to a thread to another ?
2/ is there anyway to know the list of ALL objects that belongs to a specific thread ? (for debugging purpose : check if all objects have been moved to the main thread)
3/ after the "QtConcurrent::run" execution finished, is the worker thread deleted ? So what happen to all objects that belongs to this thread ?
- if you create all your QObjects in the worker threads on the heap and then put the pointers to those objects in a QList owned by an object that resides in your main thread I don't see any problems. The QObjects will be alive until you explicitly call delete on them (with the exception that, if these QObjects have a parent, they are deleted when their parent is deleted). Finally you can iterate over the list and move every object to the main thread context.
The problem is that all objects created in the worker thread belongs to this thread.
Because this thread is deleted (or no more running, i'm not sure) after the “QtConcurrent::run” execution finished, there is no more event loop executed for this thread, and SIGNAL/SLOT can never be receive/send from/to these objects.
(executing "connect" without the connection type will make a QueuedConnection, and because of the lack of an event loop, the message is never received)
This break SIGNAL/SLOT functionnality, and have other side effects.
For the moment, my main goal is to write a function which check if I didn't forget to move an object to the main thread.
You could create the objects inside the others with a parent pointer:
p_mySocket = new QTcpSocket(this);
This would also take those to the main thread.
Yes, but the problem is that I have about hundred classes to check, and I did'nt write all of them... so I need at least an automatic check.
AFAIK, there is no automatic check, sorry.
From my POV, if it is a requirements to go that way, you must change the code as these are programming errors in that case.
bq. you must change the code as these are programming errors in that case
I agree, but in front of the huge number of files, I cannot be sure that no object was not moved to the main thread.
I know such things, but I have no other proposal then:
check each usage and file :-(