Настройка переносной общей библиотеки с циклом событий Qt - PullRequest
0 голосов
/ 09 октября 2018

Мы пытаемся написать переносную разделяемую библиотеку, которая для удобства использует некоторые классы Qt (в основном QTimer и QTcpSocket);но без графического интерфейса.Соответствующие соединения сигнал / слот, по-видимому, требуют некоторого цикла событий Qt, поэтому мы «заполняем» QCoreApplication, как указано в в этом ответе .Соответственно, мы устанавливаем рабочий объект, который выполняет тяжелую работу, и перемещаем его в QThread.

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

Мой вопрос, таким образом: есть ли способзаставить цикл обработки событий работать в главном потоке библиотеки, не блокируя его или не запуская хост-программу (что, кажется, имеет место, когда просто помещаете QCoreApplication::exec() или подобное)?Или нам нужно будет установить другую схему связи между потоками (независимо от Qt), чтобы справиться с этими передачами данных?

Поскольку мы не знаем, будет ли программное обеспечение хоста работать на QApplication или нет, в идеале я бы также проверил это перед настройкой цикла событий основного потока.Достаточно ли простого if(qApp != nullptr) для этого?

PS: Несколько вещей, которые я пробовал, но которые не работали для меня, либо:

  • Настройки до QEventLoop вstd::thread запускается из основного потока (вероятно, не работает, потому что все еще не в основном потоке)
  • Установка QEventLoop в классе основного потока и периодическое включение его функции processEvents() с использованием QTimer(вероятно, не работает из-за отсутствия цикла событий для сигнала QTimer::timeout в основной функции)
  • Запуск QCoreApplication в std::thread (выдает предупреждение во время выполнения в Windows, что QCoreApplication должно бытьначалось в основной ветке)

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

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

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

0 голосов
/ 12 октября 2018

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

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

Если хост-приложение запускает цикл событий X11, вам нужно убедиться, что ваша копия Qt использует тот же базовый цикл событий, что и хост-приложение.Обычно это цикл событий glib, и тогда он должен работать автоматически.В противном случае вам нужно будет передать пользователю файловый дескриптор примитива синхронизации, используемого циклом событий Qt, и пользователю нужно будет интегрировать его в свой цикл событий.Вы столкнетесь с той же проблемой, используете ли вы Qt или нет: использование собственного метода связи не исправит его, поскольку вам все еще нужен ожидаемый примитив, который будет взаимодействовать с любым циклом событий, который использует пользователь.

Пользователь, конечно, может опрашивать обратные вызовы, когда ему это нравится: предоставить метод mainPoll(), который перенаправляет на QCoreApplication::processEvents().

...