QApplication not created in main thread()
-
@Shidharth Don't create QApplication in other threads than main thread. How and where do you create QApplication instance?
-
@jsulm Thanks for your reply.
I have created QApplication inside a function, this function is called from .Net web application. While calling this function in .Net console application it works fine. But the error occurs only on web application.
int arg =1; char * arc = "s"; QApplication a(arg, &arc, true);
-
Hi @Shidharth,
- Does your code create and destroy QApplication multiple times?
- Do you create any QObjects before you create QApplication?
-
@JKSH makes a good point there.
Anyway, main() is the reception of the executable. A QApplication should be in the main() and be called only once. AFAI.
Kind Regards,
Carlos
-
First of all, it is safe to create QApplication in another thread. See here for an example: https://stackoverflow.com/questions/22289423/how-to-avoid-qt-app-exec-blocking-main-thread/22290909#22290909
Here's how it works. Qt marks the thread which creates the first QApplication instance as the "main thread". You won't get a warning the first time.
When you destroy that QApplication, Qt does not release all resources. For example, there will still be a hidden global QPixmapCache which needs to be accessed from the QApplication's original thread.
When you start another thread to create a new QApplication, Qt checks the thread. If Qt detects that you're using a different thread from the first QApplication's thread, then it will give you a warning.
To avoid the warning and to avoid corruption, you must make sure that the same thread creates the QApplication every time.
Alternatively, you can create only one QApplication and never destroy it. Every time you want to create a new PDF, do it in that thread.
-
@JKSH I have created single QApplication and using it for multiple times. But it throws error when calling the function multiple times from the Web application, please check the below warnings.
QObject::setParent: Cannot set parent, new parent is in a different thread
QObject::installEventFilter(): Cannot filter events for objects in a different thread -
@Shidharth said in QApplication not created in main thread():
@JKSH I have created single QApplication and using it for multiple times.
All the functions for QApplication or Qt WebKit must only be called from the QApplication's thread.
This means Qt WebKit objects (such as QWebView) must only be created in QApplication's thread.
But it throws error when calling the function multiple times from the Web application, please check the below warnings.
QObject::setParent: Cannot set parent, new parent is in a different thread
QObject::installEventFilter(): Cannot filter events for objects in a different threadYour web application starts new threads, so it must not create Qt WebKit objects directly or call Qt WebKit functions.
Instead, your web application should use emit a signal or use
QMetaObject::invokeMethod()
. The connection type must be aQt::QueuedConnection
orQt::BlockingQueuedConnection
.Here's a very simple example:
// bridge.h Bridge : public QObject { Q_OBJECT public: Bridge(QObject *parent = nullptr); public slots: void convertHtmlToPdf() { QWebView view; /* Do your PDF conversion here... */ } };
// In the QApplication thread Bridge *bridgePtr = nullptr; void run() { int argc = 1; char *argv = "s"; QApplication app(argc, &argv); // Create the bridge object Bridge b; bridgePtr = &b; // Run the QApplication app.exec(); // Clean up after the QApplication quits bridge = nullptr; }
// In another thread void convertFromWebApplication() { QMetaObject::invokeMethod(bridgePtr, "convertHtmlToPdf", Qt::BlockingQueuedConnection); } void shutdownFromWebApplication() { QMetaObject::invokeMethod(aApp, "quit", Qt::BlockingQueuedConnection); }
If you want to pass arguments or return arguments, use
Q_ARG
andQ_RETURN_ARG
. See http://doc.qt.io/qt-5/qmetaobject.html#invokeMethodWarning: The code above does not do any error checking, and it does not guard against race conditions. You must add those yourself!