C++ 阻止等待异步Qt信号
我知道,下面还有一些类似的问题,但我找不到一个具体的答案来帮助我。所以我的问题是: 我在一个应用程序上工作,该应用程序在启动时进行一些gui初始化。我必须做的事情之一就是打电话C++ 阻止等待异步Qt信号,c++,qt,qt4,C++,Qt,Qt4,我知道,下面还有一些类似的问题,但我找不到一个具体的答案来帮助我。所以我的问题是: 我在一个应用程序上工作,该应用程序在启动时进行一些gui初始化。我必须做的事情之一就是打电话 NetworkConfigurationManager::updateConfigurations () 这是一个异步调用,完成后会发出updateCompleted()信号。问题是,我的所有其他gui初始化都必须等待updateConfigurations()完成 所以我能做的就是这样: MyApp::MyApp(Q
NetworkConfigurationManager::updateConfigurations ()
这是一个异步调用,完成后会发出updateCompleted()
信号。问题是,我的所有其他gui初始化都必须等待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();
}
对我来说,分开初始化似乎不是一个好办法。我认为这会使代码更难阅读——init应该保持在一起。另一件事是:因为updateConfiguration()
是异步的,用户将能够使用GUI,它还没有给他任何信息,因为我们正在等待updateCompleted()
那么,在应用程序继续之前,是否有办法等待updateCompleted()
信号
比如:
在某些API中,有异步函数的阻塞替代方案,但在本例中没有
谢谢你的帮助。谢谢 实现这一点的方法是使用嵌套的事件循环。您只需创建自己的QEventLoop,将想要等待的任何信号连接到循环的
quit()
插槽,然后exec()
循环。这样,一旦调用该信号,它将触发QEventLoop的quit()
插槽,从而退出循环的exec()
从的工作中,如果您要等待用户注意到的时间,您可能希望显示a(或者,可能是a)
另一个解决办法是使用。这个函数是在Qt5中引入的,它完全满足您的需要
我看到该类的唯一问题是它是在QtTest模块中提供的。在我的例子中,我发现它在测试代码时非常有用,但它可能不是生产代码的最佳解决方案 是的,这是有效的,这是“阻止等待而不阻止UI”的标准模式。如果可能的话,我会尽量避免。嵌套事件循环可能会导致严重的问题,例如,用户在loop.exec()时执行随机的不可见操作,退出应用程序等,在exec()返回后使应用程序处于不可见、不一致的状态。或者:一个(用户)事件打开另一个本地事件循环,等待一个需要第一个循环完成的事件,从而导致一种准死锁。这就是为什么我建议使用一个插槽并继续使用,即使这更详细。首先:感谢您的帮助。你的答案是正确的,尽管它在我的解决方案中不起作用。我想我遇到了Frank提到的问题之一,因为我的循环无法退出。尽管如此,我还是在诺基亚Wiki()中找到了您答案的证据。谢谢大家!根据Qt/Nokia,您不应该使用QEventloop,因为它会导致失控递归(请参阅)。这应仅用于测试。还是我误读了这篇文章?这个答案对于编写自动化测试用例很方便,谢谢!弗兰克是对的——QEventLoop方法是危险的。我好不容易才发现这一点。我有一个应用程序需要以正确的顺序获取多个网页,并且逻辑在状态机中从一个函数跳到另一个函数,因此我尝试使用QEventLoop。当我这样做的时候,如果用户在事件循环中移动窗口(或某些其他东西),窗口焦点就会丢失。整个应用程序都会冻结。所有的应用程序都会冻结!点击alt tab是恢复控制的唯一方法,然后它将再次正常运行。所以是的。。。这不是一个好的解决方案。内部似乎与
chalup
的答案相同。
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();
}
MyApp::MyApp(QWidget *parent) : ....
{
doSomeInits();
{
QEventLoop loop;
loop.connect(configManager, SIGNAL(updateCompleted()), SLOT(quit()));
configManager->updateConfigurations();
loop.exec();
}
doReaminingInitsThatHadToWaitForConfigMgr();
}
MyApp::MyApp(QWidget *parent) : ....
{
doSomeInits();
{
QSpashScreen splash;
splash.connect(configManager, SIGNAL(updateCompleted()), SLOT(close()));
configManager->updateConfigurations();
splash.exec();
}
doReaminingInitsThatHadToWaitForConfigMgr();
}