Как поставить условие ожидания в Сигнал-Слот? - PullRequest
2 голосов
/ 02 октября 2011

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

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

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

  1. main создает объект My_Class A.
  2. main вызывает «start» из A.
  3. start вызывает загрузку из «WebPage»и он ожидает до тех пор, пока "WebPage" не выдаст "Закончено", а этот эмиттер, в свою очередь, вызовет "after_Load_Function", а "after_Load_Function"
    завершит свою работу.
  4. сейчас, "начало" возвращает
  5. main return

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

Ответы [ 4 ]

4 голосов
/ 02 октября 2011

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

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

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

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

0 голосов
/ 02 октября 2011

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

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

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

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

Примечания:

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

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

0 голосов
/ 02 октября 2011

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

...