Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blocked waiting for a asynchronous Qt signal

Tags:

I know, there are some similar questions to the following out there, but I couldn't find a concrete answer that helps me. So here's my problem:

I work on an application that does some gui-initialisations on start up. One of the things I have to do, is calling

NetworkConfigurationManager::updateConfigurations () 

This is a asynchronous call, which emits the updateCompleted() signal, when it is finished. The problem is, that all my other gui-initialisations have to wait until the updateConfigurations() is finished.

So what I could do would be something like this:

MyApp::MyApp(QWidget *parent) : .... {    doSomeInits();    //Now connect the signal we have to wait for    connect(configManager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationUpdated()));    configManager->updateConfigurations(); //call the async function }  void MyApp::networkConfigurationUpdated() {    doSomething();    doRemainingInitsThatHadToWaitForConfigMgr(); } 

To split up the initialisation doesn't seem a good way to me. I think it makes the code much harder to read - inits should remain together. The other thing is: Because updateConfiguration() is asynchronous, the user will be able to use the GUI, which doesn't give him any information yet, cause we are waiting for updateCompleted().

So is there a way to wait for the updateCompleted() signal, before the application continues?

like:

MyApp::MyApp(QWidget *parent) : .... {    doSomeInits();    //Now connect the signal we have to wait for    connect(configManager, SIGNAL(updateCompleted()), this, SLOT(doSomething()));    ???? //wait until doSomething() is done.    doRemainingInitsThatHadToWaitForConfigMgr(); } 

In some APIs there are blocking alternatives to asynchronous functions, but not in this case.

I appreciate any help. Thanks!

like image 630
cyphorious Avatar asked Aug 24 '10 12:08

cyphorious


People also ask

How do you wait for a signal in Qt?

Starting in Qt 5.0, QSignalSpy offers a wait method. You hook it up to a signal and wait() will block until the signal fires.

Are Qt signals asynchronous?

So in normal cases, it will be synchronous and blocking, and with queued connections it will be asynchronous and non-blocking.

How do Qt signals work?

The Qt signals/slots and property system are based on the ability to introspect the objects at runtime. Introspection means being able to list the methods and properties of an object and have all kinds of information about them such as the type of their arguments.


2 Answers

The way to do this is to use nested event loops. You simply create your own QEventLoop, connect whatever signal you want to wait for to the loop's quit() slot, then exec() the loop. This way, once the signal is called, it will trigger the QEventLoop's quit() slot, therefore exiting the loop's exec().

MyApp::MyApp(QWidget *parent) : .... {     doSomeInits();     {         QEventLoop loop;         loop.connect(configManager, SIGNAL(updateCompleted()), SLOT(quit()));         configManager->updateConfigurations();          loop.exec();     }     doReaminingInitsThatHadToWaitForConfigMgr(); } 
like image 78
chalup Avatar answered Oct 03 '22 18:10

chalup


Working from chalup's answer, if you are going to be waiting for a user-noticeable time, you might want to show a progress bar instead (or a splash screen, perhaps).

MyApp::MyApp(QWidget *parent) : .... {     doSomeInits();     {         QSpashScreen splash;         splash.connect(configManager, SIGNAL(updateCompleted()), SLOT(close()));         configManager->updateConfigurations();          splash.exec();     }     doReaminingInitsThatHadToWaitForConfigMgr(); } 
like image 33
Caleb Huitt - cjhuitt Avatar answered Oct 03 '22 17:10

Caleb Huitt - cjhuitt