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

Как избежать основной блокировки Qt app.exec()

Я новичок в Qt, но мне нужно решить сложную проблему.

Я создал ОЧЕНЬ простой графический интерфейс, который мне нужно добавить в существующее приложение на С++. Проблема в том, что я пишу только один модуль, который подключается к более крупной архитектуре, которая ограничивает мой доступ к основному потоку.

Мой код должен находиться внутри четырех следующих функций: функция Init(), которая запускается в основном потоке. и WorkerStart(), WorkerStep() и WorkerStop(), которые выполняются в рабочем потоке.

Я закодировал объекты QApplication и GUI в функции Init(). Но, конечно, вызов app.exec() в конце этой функции блокирует весь остальной код. Не работает.

Все, что я читаю, говорит, что объекты Qt gui могут работать только в основном потоке.

Итак, мой вопрос в том, как настроить мой gui в функции init() (основной поток) и разрешить ему запускать только с помощью рабочего потока с этого момента?

Я нашел это: QApplication In Non-Main Thread

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

Кажется, что добавление gui к существующей программе на С++ без блокировки в функции exec() должно быть довольно распространенной ситуацией, поэтому я чувствую, что мне не хватает чего-то очевидного. Может кто-то помочь с тем, как я могу это решить?

Большое спасибо заранее. Фил

4b9b3361

Ответ 1

В большинстве случаев "основной поток" == "поток GUI", поэтому люди используют эти термины взаимозаменяемо - даже официальная документация делает это. Я согласен с тем, что это запутывает, потому что они не обязательно должны быть одинаковыми. ^ Фактическое правило таково:

Классы GUI должны быть доступны только из потока, который создает экземпляр QApplication/QGuiApplication

С плагином, подобным вашему, вот что вам нужно сделать:

  • Создайте новый std::thread (НЕ a QThread)
  • Запустите функцию init в этом потоке. Пусть он создает экземпляр QApplication/QGuiApplication и запускает цикл событий
  • Убедитесь, что все ваши объекты GUI доступны только из этого потока.

Voila, теперь у вас есть поток GUI, который не является вашим основным потоком.


^ Примечание. Это другая история в Mac OS X. Из-за ограничений в структуре Cocoa основной поток ДОЛЖЕН быть потоком GUI. Шаги, описанные выше, будут работать на Windows/Linux, но не на Mac. Для Mac вам нужно ввести код в основной поток - см. Комментарии Kuba Ober ниже.