阻塞等待异步Qt信号

时间:2010-08-24 12:32:57

标签: c++ qt qt4

我知道,在那里有一些类似的问题,但我找不到能帮助我的具体答案。所以这是我的问题:

我正在开发一个在启动时执行一些gui-initialisations的应用程序。我要做的一件事就是打电话

NetworkConfigurationManager::updateConfigurations ()

这是一个异步调用,当它完成时会发出updateCompleted()信号。问题是,我所有其他的gui-initialisations必须等到updateConfigurations()完成。

所以我能做的就是这样:

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

分拆初始化对我来说似乎不是一个好方法。我认为它使代码更难阅读 - 内容应该保持在一起。另一件事是:因为updateConfiguration()异步,用户将能够使用GUI,它还没有给他任何信息,因为我们正在等待{{1} }。

那么在应用程序继续之前有没有办法等待updateCompleted()信号?

像:

updateCompleted()

在某些API中,存在异步函数的阻塞替代方法,但在这种情况下不存在。

我感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:23)

执行此操作的方法是使用嵌套的事件循环。您只需创建自己的QEventLoop,将要等待的任何信号连接到循环的quit()插槽,然后exec()循环。这样,一旦调用信号,它将触发QEventLoop的quit()槽,从而退出循环的exec()

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

答案 1 :(得分:7)

chalupanswer工作,如果您要等待用户明显的时间,则可能需要显示progress bar(或{{3}或许)。

MyApp::MyApp(QWidget *parent) : ....
{
    doSomeInits();
    {
        QSpashScreen splash;
        splash.connect(configManager, SIGNAL(updateCompleted()), SLOT(close()));
        configManager->updateConfigurations(); 
        splash.exec();
    }
    doReaminingInitsThatHadToWaitForConfigMgr();
}

答案 2 :(得分:1)

另一种解决方案可能是使用QSignalSpy::wait()。这个功能在Qt 5中引入,完全符合你的要求。

我在该类中看到的唯一问题是它在QtTest模块中提供。在我的情况下,我发现它在测试代码时非常有用,但它可能不是生产代码的最佳解决方案。