Параллельный запуск нескольких циклов QEventLoop (для QtNetwork)

Я пытаюсь расширить старую программу, работающую под Ubuntu/Linux Desktop, с поддержкой сети Qt. Для связи по локальной сети с этими библиотеками необходимо запустить .exec() цикла QEventLoop, чтобы действительно начать работать (т. е. принимать соединения, получать, отправлять и т. д.).

Проблема

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

Моя идея

Я уже проверил, что мне не нужен main-QEventLoop, и можно сделать еще один только для сети (т.е. вложенности). К сожалению, я не могу понять, как запустить оба цикла параллельно, так как моя программа останавливается на вложенном-.exec(), и поэтому основная программа тоже останавливается.

Итак, мое главное намерение - расширить основную программу с помощью Qt-Networking, я открыт и для других решений.


person user3085931    schedule 02.03.2016    source источник
comment
@KubaOber да, ты был совершенно прав. Если вы сделаете это ответом, я отмечу его как решение.   -  person user3085931    schedule 11.03.2016


Ответы (2)


Является ли основная программа интерактивной? Если это так, то, вероятно, он запускает основной цикл событий glib. Qt использует тот же цикл обработки событий в Linux, поэтому вам не нужно вызывать exec() в коде. Запустите цикл событий только один раз, создав экземпляр QEventLoop, отправив ему вызов quit и exec() запустив его. Затем верните управление основной программе. Ваш код по-прежнему будет выполняться по мере поступления событий (таймеры истекают, приходят сетевые пакеты и т. д.).

Замечательная особенность встроенной интеграции циклов событий, которую вы получаете с Qt, заключается в том, что вам не нужно делать основную exec(), если кто-то другой уже вращает цикл.

Итак, вот как может выглядеть плагин Qt для приложения GTK в Linux:

extern "C" void pluginInit() {
  new QApplication;
  QEventLoop loop;
  QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
  loop.exec();
}

extern "C" void pluginDestroy() {
  delete qApp;
}

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

Я бы предпочел такое решение многопоточности, поскольку в целом оно звучит более стабильно.

Если многопоточность для вас нестабильна, вы делаете это неправильно. Сетевая поддержка будет отлично работать в выделенном потоке. Вероятно, это одно из немногих законных применений второго потока, поскольку таким образом обработка ваших сетевых данных не будет отложена из-за сладкого времени, которое рендерер пользовательского пространства и компоновщик тратят на сборку того, что вы видите на экране.

person Kuba hasn't forgotten Monica    schedule 11.03.2016
comment
Работает как шарм. Я никогда не думал об использовании invokeMethod(...). Большое спасибо - person user3085931; 16.03.2016

Я бы предложил использовать QThread, если вам нужно запустить 2 независимых цикла событий.

person Paraboloid87    schedule 02.03.2016
comment
гарантируется ли тогда, что мои входящие соединения будут приняты (процедурой сигнала/слота), или может случиться так, что запрос будет потерян, потому что поток в это время не выполнялся? - person user3085931; 04.03.2016
comment
Вы должны убедиться, что поток работает. Объекты, «живущие» в потоке, не будут запущены, если поток не запущен. По этой причине вы должны создать поток, переместить объект в поток и запустить поток. Затем вы можете установить соединение. - person Paraboloid87; 04.03.2016