Как поместить условие ожидания в сигнальный слот?

#c #qt #signals-slots

#c #qt #сигналы-слоты

Вопрос:

Я делаю один веб-проект. Недавно я столкнулся с этой ситуацией. Это всего лишь заглушка

 Class My_Class
{
public:
    My_Class();
    void start();
public slots():
    void after_Load_Function();
}

My_Class::My_Class()
{
    //Some initializations
    connect(WebPage,SIGNAL(finished()),this,SLOTS(after_Load_Function()));
}

void My_Class::start()
{
    WebPage->load();
}

void My_Class::after_Load_Function()
{
    //Do something with the finished WebPage
}

int main(int argc,char * argv[])
{
    //Some Qt things

    My_Class a;
    a.start();
}
  

«Веб-страница» выдает сигнал «готово» при полной загрузке.
Теперь проблема в том, что перед загрузкой «веб-страницы» возвращается «старт». Таким образом, управление достигает «основного». Итак, теперь элемент управления должен возвращаться из «start» только после того, как «after_Load_Function» завершит свою работу. Таким образом, я хочу следующую последовательность,

  1. main создает объект My_Class A.
  2. основные вызовы «начинаются» с A.
  3. запуск вызывает загрузку с «веб-страницы» и ожидает, пока «веб-страница» не выдаст «готово», и это, в свою очередь, вызывает «after_Load_Function», а «after_Load_Function»
    завершает свою работу.
  4. теперь «старт» возвращает
  5. основные возвраты

Но я не знаю, как создать такое условие ожидания. Как я могу это сделать?

Комментарии:

1. Что такое WebPage ? Если он основан на классах Qt Webkit, весьма вероятно, что он полагается на цикл событий для запуска, чтобы он мог завершиться. Блокировка включения start предотвратила бы это и, таким образом, заблокировала бы ваше приложение. Почему вы хотите дождаться этого события?

2. Из простого беглого просмотра этого вопроса, похоже, речь идет о некоторых сторонних библиотечных средствах, т.Е. охватываемых RTFM.

3. @Mat проблема в том, что перед загрузкой «веб-страницы» возвращается «пуск»

4. @prabhakaran: Я понимаю, что происходит, но не понимаю, почему это проблема . Блокировка основного потока в Qt обычно является неправильным решением и может привести к тупиковой ситуации вашего приложения. Почему вы не можете сделать все, что нужно сделать в слоте (или даже позже)? Зависит ли веб-страница от цикла событий?

5. @Alf В этом проекте я использую только Qt.

Ответ №1:

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

 void My_Class::start()
{
    QEventLoop qel;
    QObject::connect(WebPage, SIGNAL(finished()), amp;qel, SLOT(quit()));

    WebPage->load();
    qel.exec();
}
  

Я использовал это раньше, и это работает нормально. Я не советую использовать это слишком часто, потому что он будет обрабатывать события, в том числе те, которые вызывающий объект start , возможно, не ожидает обработки во время вызова start , поэтому вам нужно задокументировать это для своих абонентов. Вы можете предотвратить обработку некоторых событий, передав определенные флаги QEventLoop::exec , например, запретить обрабатывать события пользовательского интерфейса.

Ответ №2:

Вы никогда не должны ждать в коде пользовательского интерфейса. Вам нужно разбить вашу «основную» функцию на части, чтобы более поздняя часть могла выполняться отдельно.

Ответ №3:

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

Комментарии:

1. За исключением того, что вы не должны заставлять основной поток ждать в приложении пользовательского интерфейса.

Ответ №4:

WebPage->load() Метод является асинхронным, что означает, что он запускается немедленно, а не после завершения загрузки. Операция выполняется в фоновом режиме, пока вы занимаетесь другими делами.

Это считается хорошей вещью, поскольку позволяет вашему приложению быть более отзывчивым и выполнять больше работы. Например, если ваше приложение имеет графический интерфейс, вы можете обновить графический интерфейс с помощью какой-либо анимации, которая указывает, что веб-страница извлекается.

Если вы предпочитаете модель, в которой приложение блокируется до полной загрузки страницы, рассмотрите возможность внесения этого изменения:

 void My_Class::start()
{
    WebPage->load();
    while (!WebPage->isLoaded())
        Sleep(1);
    after_Load_Function();
}
  

Примечания:

  • Sleep функция будет работать в Windows. Если вы используете ОС Unix, вы можете использовать usleep .
  • поскольку эта функция будет эффективно блокироваться до загрузки веб-страницы, нет причин использовать сигнал от объекта веб-страницы, вы можете просто вызвать свой обработчик после завершения ожидания, так как это заставит ваш обработчик запускаться в том же потоке.
  • делать это действительно плохая практика. Вам может сойти с рук, если ваша программа работает из командной строки и не имеет графического интерфейса пользователя и / или цикла событий, но вам следует подумать о лучшем дизайне вашего приложения, чтобы загрузка веб-страниц не блокировала все приложение.