tags:

views:

99

answers:

2

Hello!

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();
   doReaminingInitsThatHadToWaitForConfigMgr();
}

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 informations yet, cause we are waiting for updateCompleted().

So is there a way that 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 the are blocking alternatives to asynchronous functions, but not in this case.

I appreciate any help. Thanks!

+3  A: 
MyApp::MyApp(QWidget *parent) : ....
{
    doSomeInits();
    {
        QEventLoop loop;
        loop.connect(configManager, SIGNAL(updateCompleted()), SLOT(quit()));
        configManager->updateConfigurations(); 
        loop.exec();
    }
    doReaminingInitsThatHadToWaitForConfigMgr();
}

Note: I haven't event compiled this snippet, but IMHO local QEventLoop is a way to go.

chalup
Yes, this works, and it's the standard pattern for "blocking wait without blocking the UI". I would avoid it though if possible. Nested event loops can cause serious headaches, e.g. the user doing random unforseen stuff while loop.exec(), quitting the application etc., leaving the application in an unforseen, inconsistent state after exec() returns.Or: An (user) event opens another local event loop waiting for an event which requires the first loop to finish, causing kind of a quasi-deadlock.That's why I recommend to use a slot and continue there, even if that is more verbose.
Frank
First of all: thanks for your help. Your answer is right, although it is not working in my solution. I guess I have one of the problems mentioned by Frank, cause my loop is unable to quit.Nevertheless I found a proof to your answer in the Nokia Wiki (http://wiki.forum.nokia.com/index.php/TSQ001335_-_Asynchronous_operations_in_S60_and_Qt) . So thank you all!
cyphorious
+1  A: 

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();
}
Caleb Huitt - cjhuitt