阻塞等待异步 Qt 信号

发布于 2024-09-15 22:42:52 字数 1377 浏览 2 评论 0原文

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

我正在开发一个在启动时进行一些图形用户界面初始化的应用程序。我必须做的一件事是调用

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

把回忆走一遍 2024-09-22 22:42:52

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

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

MyApp::MyApp(QWidget *parent) : ....
{
    doSomeInits();
    {
        QEventLoop loop;
        loop.connect(configManager, SIGNAL(updateCompleted()), SLOT(quit()));
        configManager->updateConfigurations(); 
        loop.exec();
    }
    doReaminingInitsThatHadToWaitForConfigMgr();
}
梦年海沫深 2024-09-22 22:42:52

chalup答案,如果您要等待用户可察觉的时间,您可能需要显示 进度条 代替(或 启动画面,也许)。

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

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();
}
氛圍 2024-09-22 22:42:52

另一种解决方案可能是使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文