Я знаю, что есть несколько подобных вопросов, но я не мог найти конкретный ответ, который мне помог бы. Итак, вот моя проблема:
Я работаю над приложением, которое выполняет некоторые графические инициализации при запуске. Одна из вещей, которую я должен сделать, это вызвать
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 есть блокирующие альтернативы асинхронным функциям, но не в этом случае.
Я ценю любую помощь. Спасибо!
Для этого можно использовать вложенные циклы обработки событий. Вы просто создаете свой собственный 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();
}
Работая с chalup ответом , если вы собираетесь дождаться времени, заметного для пользователя, вы можете отобразить индикатор выполнения вместо этого (или, возможно, заставку ).
MyApp::MyApp(QWidget *parent) : ....
{
doSomeInits();
{
QSpashScreen splash;
splash.connect(configManager, SIGNAL(updateCompleted()), SLOT(close()));
configManager->updateConfigurations();
splash.exec();
}
doReaminingInitsThatHadToWaitForConfigMgr();
}