Заблокировано ожидание асинхронного сигнала Qt

Я знаю, что есть несколько подобных вопросов, но я не мог найти конкретный ответ, который мне помог бы. Итак, вот моя проблема:

Я работаю над приложением, которое выполняет некоторые графические инициализации при запуске. Одна из вещей, которую я должен сделать, это вызвать

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

Разделить инициализацию не кажется мне хорошим способом. Я думаю, что это делает код намного сложнее для чтения - элементы должны оставаться вместе. Другое дело: поскольку updateConfiguration () является асинхронным , пользователь сможет использовать графический интерфейс, который пока не дает ему никакой информации, потому что мы ждем 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 есть блокирующие альтернативы асинхронным функциям, но не в этом случае.

Я ценю любую помощь. Спасибо!

22
задан Étienne 8 March 2016 в 21:47
поделиться

2 ответа

Для этого можно использовать вложенные циклы обработки событий. Вы просто создаете свой собственный 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();
}
23
ответ дан 29 November 2019 в 05:15
поделиться

Работая с chalup ответом , если вы собираетесь дождаться времени, заметного для пользователя, вы можете отобразить индикатор выполнения вместо этого (или, возможно, заставку ).

MyApp::MyApp(QWidget *parent) : ....
{
    doSomeInits();
    {
        QSpashScreen splash;
        splash.connect(configManager, SIGNAL(updateCompleted()), SLOT(close()));
        configManager->updateConfigurations(); 
        splash.exec();
    }
    doReaminingInitsThatHadToWaitForConfigMgr();
}
7
ответ дан 29 November 2019 в 05:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: