Подтвердить что ты не робот

Как интегрировать основной цикл Boost.Asio в инфраструктуре графического интерфейса, например Qt4 или GTK

Есть ли способ интегрировать Boost.Asio с Qt4 (предпочтительный) или основной цикл GTK? GTK предоставляет опрос (2), такой как API, поэтому технически это должно быть возможно. Qt предоставляет свой собственный сетевой уровень, однако я предпочитаю использовать существующий код, написанный для Boost.Asio. Я хочу интегрировать их без, используя дополнительный поток.

Есть ли какая-нибудь ссылка, как это сделать для Qt4 (предпочтительный) или GTKmm?

Спасибо.

Edit

Я хочу очистить несколько вещей, чтобы облегчить ответ. Оба Qt и GTKmm обеспечивают функция "select like":

Итак, вопрос заключается в том, как интегрировать существующие "селекторы/опылители" в качестве реактора для Boost.Asio io_service. Сегодня Boost.Asio может использовать select, kqueue, epoll,/dev/poll и iocp в качестве службы реакторов/проакторов. Я хочу интегрировать его в основной цикл графического интерфейса.

Любые предложения и решения (лучше) приветствуются.

4b9b3361

Ответ 1

Это довольно старый вопрос, но для тех, кто сейчас его читает, я хотел бы поделиться моим кодом, который является реализацией QAbstractEventDispatcher для boost:: asio.

Все, что вам нужно, это добавить следующую строку перед созданием QApplication (обычно это в main()).

QApplication::setEventDispatcher(new QAsioEventDispatcher(my_io_service));

Это приведет к тому, что io_service запускается вместе с qt-приложением в одном потоке без дополнительной задержки и снижения производительности (например, в решении с вызовом io_service:: poll() "время от времени" ).

К сожалению, мое решение предназначено только для систем posix, так как оно использует asio:: posix:: stream_descriptor. Для поддержки Windows может потребоваться совершенно другой подход или совсем аналогичный - я действительно не знаю.

Ответ 2

Простой: Создайте слот QT, который вызывает io_service::poll_one(), принадлежащий gui. Подключите этот слот к сигналу QT tick.

В глубине: К счастью для вас Boost.Asio очень хорошо спроектирован. Существует множество опций о том, как обеспечить поток выполнения для основных асинхронных внутренних компонентов. Люди уже упоминают использование io_service::run(), блокирующий вызов со многими недостатками.

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

Наивный подход состоит в том, чтобы просто выделить один поток (или таймер) для запуска io_service::run() и обработчик завершения Asio отправит сигнал gui. Это будет работать.

Вместо этого вы можете использовать гарантию, что обработчики завершения будут вызываться только в потоке выполнения вызывающего io_service. У вас нет потока вызовов gui io_service::run(), поскольку он блокирует и может висеть gui. Вместо этого используйте io_service::poll() или io_service::poll_one(). Это приведет к вызову любых обработчиков завершения Asio, которые будут вызваны из потока gui. Поскольку обработчики работают в потоке gui, они могут изменять виджеты.

Теперь вам нужно убедиться, что io_service получает возможность регулярно запускаться. Я рекомендую несколько раз повторить вызов сигнала gui poll_one(). Я считаю, что QT имеет сигнал тика, который бы сделал трюк. Вы могли бы, конечно, свернуть свой собственный сигнал QT для большего контроля.

Ответ 3

Если я правильно понял ваш вопрос, у вас есть код, написанный для Boost.Asio. Вы хотите использовать этот код внутри приложения GUI.

В вашем вопросе непонятно, хотите ли вы обрезать сетевые уровни Qt/Gtk через asynio, чтобы ваш код работал, если вы просто ищете решение для объединения циклов событий gui и asynio.

Я возьму второй случай.

Оба Qt и Gtk имеют методы для интеграции иностранных событий в их цикл событий. См. Например qtgtk, где цикл событий Qt подключен к Gtk.

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

После быстрого просмотра boost asio, я думаю, вам нужно сделать следующее:

  • имеют повторяющийся QTimer с нулевой длительностью, который вызывает io_service:: run() все время. Таким образом, boost:: asio будет вызывать ваш обработчик завершения, как только ваша асинхронная операция будет завершена.
  • в вашем обработчике завершения, два варианта:
    • если ваша операция завершения является длинной, отделенной от графического интерфейса пользователя, выполняйте свою деятельность и убедитесь, что вы регулярно вызываете qApp.processEvents(), чтобы поддерживать графический интерфейс.
    • Если вы просто хотите общаться с gui:

Ответ 4

Возможна интеграция основных петель. Это просто большая боль (и я еще не попробовал).

Запуск io_service:: run() в отдельном потоке - это, вероятно, путь.