Why the main thread is needed for QCoreApplication?
-
When we start QCoreApplication from the thread that differs from the main...
What do you mean by "start the QCoreApplication"? Do you mean the event loop? If so then the restriction is that it has to run in the same thread the QCoreApplication was created in. Btw. that's what Qt calls "main thread" - it's the thread the QCoreApplication was created in and its event loop is run in. It's not necessarily the thread the "main()" of your app runs in.
So there's no restriction to creating QCoreApplication object in another thread. The restriction is only that its event loop must run in the thread the object was created in. For example this sample runs just fine:
#include <QCoreApplication> #include <QTimer> #include <thread> void runsInOtherThread(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTimer::singleShot(1000, &a, &QCoreApplication::quit); //spin for one second and quit a.exec(); } int main(int argc, char *argv[]) { std::thread t(runsInOtherThread, argc, argv); // do some stuff while Qt runs in another thread // ... t.join(); return 0; }
-
Thank you for reply. I was confused by the terminology in Qt documentation and qWarnings when I ran my code.
-
When we start QCoreApplication from the thread that differs from the main...
What do you mean by "start the QCoreApplication"? Do you mean the event loop? If so then the restriction is that it has to run in the same thread the QCoreApplication was created in. Btw. that's what Qt calls "main thread" - it's the thread the QCoreApplication was created in and its event loop is run in. It's not necessarily the thread the "main()" of your app runs in.
So there's no restriction to creating QCoreApplication object in another thread. The restriction is only that its event loop must run in the thread the object was created in. For example this sample runs just fine:
#include <QCoreApplication> #include <QTimer> #include <thread> void runsInOtherThread(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTimer::singleShot(1000, &a, &QCoreApplication::quit); //spin for one second and quit a.exec(); } int main(int argc, char *argv[]) { std::thread t(runsInOtherThread, argc, argv); // do some stuff while Qt runs in another thread // ... t.join(); return 0; }
@Chris-Kawa But there's still the warning: "WARNING: QApplication was not created in the main() thread."
-
Do you mean my example is giving you this warning or you get it in your app?
-
Do you mean my example is giving you this warning or you get it in your app?
@Chris-Kawa In my app. Example is ok. Maybe I've missed something. Creating and exec-ing QCoreApplication in another thread and still getting the warning.
-
Couple of things to check:
Make sure you don't have any static QObjects (which is bad even in single thread anyway).
Make sure you're not instantiating any QObjects before the app object is created (in any thread!). This also means that you can't for example create QCoreApplication object in a thread managed by QThread object. -
Couple of things to check:
Make sure you don't have any static QObjects (which is bad even in single thread anyway).
Make sure you're not instantiating any QObjects before the app object is created (in any thread!). This also means that you can't for example create QCoreApplication object in a thread managed by QThread object.@Chris-Kawa I've found single threaded solution that's suitable for me.
I used temporary QCoreApplication object like this.
int argc = 0; char** argv = nullptr; QCoreApplication qtApp(argc, argv); Internal::FactoryWorker worker; QObject::connect(&worker, SIGNAL(doWork(cocos2d::Node*, const QString&)), &worker, SLOT(onDoWork(cocos2d::Node*, const QString&)), Qt::QueuedConnection); QObject::connect(&worker, SIGNAL(doWork(cocos2d::Node*, const QString&)), &qtApp, SLOT(quit()), Qt::QueuedConnection); worker.doWork(parentNode, fileName); qtApp.exec();
-
In that case there's no need for the connects or event loop, since all you do in it is start
onDoWork
and immediately after it quit the loop.
Would be the same if you did:int argc = 0; char** argv = nullptr; QCoreApplication qtApp(argc, argv); Internal::FactoryWorker().OnDoWork(parentNode, fileName);
-
In that case there's no need for the connects or event loop, since all you do in it is start
onDoWork
and immediately after it quit the loop.
Would be the same if you did:int argc = 0; char** argv = nullptr; QCoreApplication qtApp(argc, argv); Internal::FactoryWorker().OnDoWork(parentNode, fileName);
@Chris-Kawa The code into the OnDoWork relies on event loop so I should use it. OnDoWork contains parts of QtCreator modified by me for the project purposes.
-
But you quit the loop right after the call to onDoWork, so I assume onDoWork is blocking (otherwise it makes no sense).
If onDoWork is blocking then there's no loop processing anyway until it finishes, at which point the loop quits (because of the second connect). Am I missing something? Event processing doesn't happen when you're in a blocking function in a single threaded execution.