C++ 阻塞等待异步 Qt 信号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3556421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:07:30  来源:igfitidea点击:

Blocked waiting for a asynchronous Qt signal

c++qtqt4

提问by cyphorious

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

我正在开发一个在启动时进行一些 gui 初始化的应用程序。我必须做的一件事就是打电话

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.

这是一个异步调用,updateCompleted()它在完成时发出信号。问题是,我所有其他的 gui 初始化都必须等到updateConfigurations()完成。

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().

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

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

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

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.

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

I appreciate any help. Thanks!

我很感激任何帮助。谢谢!

回答by chalup

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().

这样做的方法是使用嵌套的事件循环。您只需创建自己的 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();
}

回答by Caleb Huitt - cjhuitt

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

chalup答案开始,如果您要等待用户注意的时间,您可能希望改为显示进度条(或者可能是启动画面)。

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

回答by piponazo

Another solution could be to use QSignalSpy::wait(). This function was introduced in Qt 5 and does exactly what you want.

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

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.

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