阻塞等待异步 Qt 信号
我知道,有一些与以下类似的问题,但我找不到对我有帮助的具体答案。所以这是我的问题:
我正在开发一个在启动时进行一些图形用户界面初始化的应用程序。我必须做的一件事是调用
NetworkConfigurationManager::updateConfigurations ()
This is a asynchronous call,它在完成时发出 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();
}
分割初始化对我来说似乎不是一个好方法。我认为这使得代码更难阅读 - 初始化应该保持在一起。另一件事是:因为 updateConfiguration()
是异步,用户将能够使用 GUI,但它还没有给他任何信息,因为我们正在等待对于updateCompleted()
。
那么有没有办法在应用程序继续之前等待 updateCompleted()
信号?
例如:
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();
}
在某些 API 中,有异步函数的阻塞替代方案,但在本例中没有案件。
我很感激任何帮助。谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
执行此操作的方法是使用嵌套事件循环。您只需创建自己的 QEventLoop,将您想要等待的任何信号连接到循环的
quit()
插槽,然后将exec()
连接到循环。这样,一旦调用信号,它将触发 QEventLoop 的quit()
槽,从而退出循环的exec()
。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, thenexec()
the loop. This way, once the signal is called, it will trigger the QEventLoop'squit()
slot, therefore exiting the loop'sexec()
.从 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).
另一种解决方案可能是使用 QSignalSpy::wait()。该函数是在 Qt 5 中引入的,并且完全可以满足您的需求。
我看到该类的唯一问题是它是在 QtTest 模块中提供的。就我而言,我发现它在测试代码时非常有用,但它可能不是生产代码的最佳解决方案。
Another solution could be to use QSignalSpy::wait(). This function was introduced in Qt 5 and does exactly what you want.
The only problem I see with that class is that it is provided in the QtTest module. In my case I find it very useful when testing code, but it might be not the best solution for production code.