April 30, 2012

Bekos Bekos
Lab Rat
34 posts

[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

9 replies

April 30, 2012

d2uriel d2uriel
Lab Rat
80 posts

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.

 Signature 

“Do not judge, and you will never be mistaken.” - Jean-Jacques Rousseau

April 30, 2012

1+1=10 1+1=10
Hobby Entomologist
643 posts

Bekos wrote:
Why is this happening?

Why the blocking occurs?

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:

  1. while(1) //QDialog::exec()
  2. {
  3. //...
  4. }
  5.  
  6. while(1) //QApplication::exec()
  7. {
  8. //...
  9. }

Bekos wrote:
But isn’t this a bad Qt practice?

Yes, it a bad Qt practice.

You should use QDialog::show() or QDialog::open() instead of QDialog::exec() in most cases.

April 30, 2012

Volker Volker
Ant Farmer
5428 posts

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:

  1. QApplication a(argc, argv);
  2.  
  3. MyDialog dlg;
  4. QTimer::singleShot(0, &dlg, SLOT(exec()));
  5.  
  6. a.exec();

The timer fires only when the application event loop has started and calls exec() on your dialog.

April 30, 2012

1+1=10 1+1=10
Hobby Entomologist
643 posts

Yes, more or less that will look like this,

  1. while(1) //QApplication::exec()
  2. {
  3.     //...
  4.         //...
  5.         while(1) //QDialog::exec()
  6.         {
  7.             //...
  8.         }
  9.     //...
  10. }

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/

May 1, 2012

Bekos Bekos
Lab Rat
34 posts

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:

  1. QDialog myDialog;
  2. myDialog.show();
  3. myQApplicationObject.exec();

While this will block at QApplication::exec():

  1. QDialog myDialog;
  2. myDialog.exec();
  3. 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

May 1, 2012

1+1=10 1+1=10
Hobby Entomologist
643 posts

If your

  1. 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().

May 1, 2012

1+1=10 1+1=10
Hobby Entomologist
643 posts

Bekos wrote:
Hello everyone,

By the way, the reason I use QDialog::exec() is because it returns the selection (OK/Canel) of the user.

You can get accepted() and rejected() too when you using QDialog::show() or QDialog::open().

May 1, 2012

d2uriel d2uriel
Lab Rat
80 posts

1+1=2 wrote:

Bekos wrote:
Hello everyone,

By the way, the reason I use QDialog::exec() is because it returns the selection (OK/Canel) of the user.

You can get accepted() and rejected() too when you using QDialog::show() or QDialog::open().


But for that you need to have an event loop stared within the QApplication object, right?

 Signature 

“Do not judge, and you will never be mistaken.” - Jean-Jacques Rousseau

May 2, 2012

Bekos Bekos
Lab Rat
34 posts

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.

1+1=2 wrote:
If your
  1. myDialog

is your only Widget.

When it’s closed, your application will be marked as finished. so QApplication::exec() will exit ASAP.

The reason I use exec() and not show() or open() is because the call is inside a loop like this:

  1. bool keepLooping = true;
  2. do
  3. {
  4.     QDialog myDialog
  5.     int result = myDialog.exec();
  6.     if(result) {
  7.         if(something) keepLooping = false;
  8.     } else {
  9.         keepLooping = false;
  10.     }
  11. } while(keepLooping);
  12.  
  13. myQApplication.exec();
  14.  
  15. // 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:

  1. QTimer::singleShot(0, &myQApplication, SLOT(quit()));

..before calling QApplication::exec();

Thanks a lot for your help guys!

Cheers,
Bekos

 
  ‹‹ [SOLVED]QStandardItemModel::itemChanged(QStandardItem*) signal and QAbstractScrollArea::paintEvent ( QPaintEvent * event ) function      someting wrong with currentPath on linux ››

You must log in to post a reply. Not a member yet? Register here!