[Solved] QDialog::exec() makes QApplication::exec() to block for ever.
-
Hello QTers!
I Have a simple problem with Qt. At the start of my application I create a QApplication object.
Durring the application startup, in a particular case (but not always), before creating any windows and before calling QApplication::exec() I create QDialog, I call QDialog::exec() and then I exit the application. But just before I exit the application, I call QApplication::exec(). This will make my application to block and stay there forever. If I use the debugger I can see that it is blocked in file "qeventdispatcher_win.cpp" at the function: MsgWaitForMultipleObjectsEx(.....). Why is this happening? I know that I could remove the QApplication::exec() because after calling QDialog::exec(), I always want to quit the application. But isn't this a bad Qt practice? Why the blocking occurs? Any idea? Thanks a lot for your time!Cheers,
Bekos -
The question is why do you pop up a QDialog before running your application? QApplication::exec() is starting an event loop and that's why it's blocking your app. If you don't have a normal GUI where user can do stuff then you probably don't need to run the exec() method of your QApplication object.
-
[quote author="Bekos" date="1335802143"] Why is this happening?
Why the blocking occurs?
[/quote]You should know that, QDialog::exec()/QMenu::exec()/QCoreApplication::exec()/... are used to start eventloop. A eventloop is an infinit loop.
so, your code will looks like this:
@
while(1) //QDialog::exec()
{
//...
}while(1) //QApplication::exec()
{
//...
}
@[quote author="Bekos" date="1335802143"] But isn't this a bad Qt practice?
[/quote]Yes, it a bad Qt practice.
You should use QDialog::show() or QDialog::open() instead of QDialog::exec() in most cases.
-
The QApplication event loop should be the first one to be started. For your use case, I would utilize a zero timeout, single shot timer:
@
QApplication a(argc, argv);MyDialog dlg;
QTimer::singleShot(0, &dlg, SLOT(exec()));a.exec();
@The timer fires only when the application event loop has started and calls exec() on your dialog.
-
Yes, more or less that will look like this,
@
while(1) //QApplication::exec()
{
//...
//...
while(1) //QDialog::exec()
{
//...
}
//...
}
@
but seems
"this is one of the patterns that can lead to unpredictable flow of logic" -
Hello everyone,
Thank you so much for your replies. I have a better understanding of how the QApplication::exec() works. But still, I do not understand is why when I close the dialog box (by clicking the ok/cancel button or the 'X' button) this will NOT block:
@
QDialog myDialog;
myDialog.show();
myQApplicationObject.exec();
@While this will block at QApplication::exec():
@
QDialog myDialog;
myDialog.exec();
myQApplicationObject.exec();
@By the way, the reason I use QDialog::exec() is because it returns the selection (OK/Canel) of the user.
Thanks a lot!
Cheers,
Bekos -
If your
@
myDialog
@
is your only Widget.When it's closed, your application will be marked as finished. so QApplication::exec() will exit ASAP.
In addition, you can give a try to QDialog::open() , which is more prefer to QDialog::exec().
-
[quote author="Bekos" date="1335887145"]Hello everyone,
By the way, the reason I use QDialog::exec() is because it returns the selection (OK/Canel) of the user.
[/quote]You can get accepted() and rejected() too when you using QDialog::show() or QDialog::open().
-
[quote author="1+1=2" date="1335894356"]
[quote author="Bekos" date="1335887145"]Hello everyone,By the way, the reason I use QDialog::exec() is because it returns the selection (OK/Canel) of the user.
[/quote]You can get accepted() and rejected() too when you using QDialog::show() or QDialog::open().[/quote]
But for that you need to have an event loop stared within the QApplication object, right? -
In both cases I close the dialog. But only the one using QDialog::show() will NOT block at QApplication::exec(). I read somewhere that this happens because my QDialog has no parent widget assigned.
[quote author="1+1=2" date="1335891728"]If your
@
myDialog
@
is your only Widget.When it's closed, your application will be marked as finished. so QApplication::exec() will exit ASAP.
[/quote]The reason I use exec() and not show() or open() is because the call is inside a loop like this:
@
bool keepLooping = true;
do
{
QDialog myDialog
int result = myDialog.exec();
if(result) {
if(something) keepLooping = false;
} else {
keepLooping = false;
}
} while(keepLooping);myQApplication.exec();
// The application exits now
@This will only work with QDialog::exec().
I guess the QApplication::exec() at the end of the code above is reduntant at this particular case because the application is going to quit anyway. To be honset I do not know why it is there at first place (it is a big project I am not the one who wrote this code). An alternative solution would be to add:@
QTimer::singleShot(0, &myQApplication, SLOT(quit()));
@..before calling QApplication::exec();
Thanks a lot for your help guys!
Cheers,
Bekos