Why the main thread is needed for QCoreApplication?
-
When we start QCoreApplication from the thread that differs from the main we see qWarning about it and QCoreApplication::exec returns -1.
I haven't found any fundamental reasons why QCoreApplication should work only from the main thread. There's such reason for QApplication because many platforms require that GUI must work from the main thread. But what about QCoreApplication?
Does Qt EventLoop-ing requires to work only from the main thread?I think that there should be QCoreApplication-based solutions that support Qt EventLooping from separate threads. That's so because if there's no way to implement that thing it means that we cannot write libraries based on Qt and use them in projects that have no QApplication objects. But if we could run Qt EventLooping in the separate thread then we can run libraries that interact with non-Qt projects.
-
Chris Kawa Lifetime Qt Championwrote on 12 Oct 2015, 19:56 last edited by Chris Kawa 10 Dec 2015, 19:56
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.
-
@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?
-
@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. -
@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);
-
@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.
7/11