Reputation: 1479
I have a couple questions.
Is it possible to initialize a QApplication object on one thread and destroy it on another?
Why does QApplication have to run on the same thread in which it was allocated?
Is it possible to run QApplication::processEvents()
on a different thread from where the QApplication object was created? Will this work if the thread to call processEvents was a non-QT thread?
Upvotes: 1
Views: 3626
Reputation: 98425
It may be possible but Qt is not tested for it. I imagine that it's possible to hack that in - you'd need code changes. It won't ever work on MacOS, unless you're having only QCoreApplication
in mind - neither the QApp..
nor QGuiApp..
supports other threads on that platform, and possibly on other platforms as well (Windows excepted). I have no idea why would you do that, though. Once the QApplication
event loop is running on the given thread, it can terminate on command and automatically destroy the application instance. In fact, it's trivial:
int main(int argc, char *argv[]) {
QScopedPointer<QCoreApplication> app(new QCoreApplication(argc, argv));
QtConcurrent::run([]{
// this runs in a worker thread, and causes the application
// object to destroy itself and then the program to exit
QThread::sleep(2);
QCoreApplication::quit();
});
auto rc = app.exec();
app.reset();
// perhaps do some other processing here that doesn't need
// a qApp instance
return rc;
}
Why not? QApplication
doesn't have to "run" at all, so who cares? You can run an event loop on any thread, and the one in the main thread doesn't need to run at all unless you have some objects in the main thread that you want to deliver events to. The event loop in the main thread is special because that's the only one where QWidget
instances are supported. That's a Mac OS limitation, so if you want to write portable code, you can only instantiate QApplication
on the main thread (i.e. something that has int main()
on the call stack).
Yes, with the caveat that it doesn't do what you likely think it might be doing. The meaning of QCoreApplication::processEvents
means "drain the event queue of the current thread". In Qt, an event loop is a per-thread resource. You can run an event loop on any thread - in fact, QThread::run
does precisely that: its run()
does, in essence QEventLoop().exec()
.
And you can only drain the event loop of whatever thread you're in, because there's no access provided to any other event loop - it wouldn't make sense: "draining" an event queue means dispatching events in the thread of the event loop that runs on that queue, and when you execute in any given thread, you by definition aren't executing code in some other thread and thus can't drain the event queue there. QCoreApplication::processEvents
is equivalent to QAbstractEventDispatcher::instance()->processEvents()
, where instance()
is the event dispatcher instance in the current thread.
Now you might say: But hey, what if we could take the event queue data that belongs to some other thread, and invoke all those QObject::event
methods in another thread? This is not only not designed to ever work, you're might simply deadlock on internal Qt mutexes and that'd be the end of it. There's no point to it anyway. On most any platform, you can send the equivalent of an interruptible sleep signal to any thread, and inject a code to execute - i.e. QCoreApplication::processEvents
- within that signal. On Windows, you'd use APCs for it, on Unix it'd be some combination of signals and other clever code. It is possible to emulate APCs to an extent by doing stack inspection to determine whether the context is safe, and if so doing things that would not otherwise be allowed.
There's no such thing as a "non-Qt" thread. A thread is a platform resource, by definition. QThread
is not a "Qt" thread. It's a handle to the platform's thread resource. Even better: it's a handle that's automatically created when there's a demand for it, so you can always refer to the current thread, even if your code hasn't created such a handle explicitly before.
Perhaps you need to tell us what you're trying to do. There's something very fundamental that's missing in your question.
Upvotes: 6