[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"

    http://labs.qt.nokia.com/2010/02/23/unpredictable-exec/



  • 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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.