Связь с потоком GUI, который не является основным потоком - PullRequest
3 голосов
/ 22 сентября 2019

Мне удалось реализовать приложение на основе Qt с графическим интерфейсом в рабочем C ++ std::thread, как описано здесь .Теперь мне нужны как основной, так и рабочий потоки для связи.

Мой вопрос таков: как я могу передавать сообщения (массив с плавающей точкой) из основного потока в рабочий поток, чтобы я мог обновить графический интерфейс?

У меня есть приложение, которое выполняет обработку сигналов в режиме реального времени.Моя цель - создать графический интерфейс Qt, который можно подключить к моему приложению, чтобы визуализировать различные сигналы, не влияя на аспект в реальном времени.Я исследовал различные методы для достижения этой цели и пришел к выводу, что этот пост достаточно подробно описывает то, что мне нужно, и предлагает решение для этого.Тем не менее, нет никакой информации о том, как основной и рабочий потоки могут взаимодействовать друг с другом.

Я пытался использовать подход Futures / Promises, описанный здесь , для осуществления связи между потоками.Хотя я смог запустить этот пример, я не смог интегрировать его в свой проект.Причина заключается в том, что этот подход основан на наличии занятого цикла внутри рабочего потока, который постоянно проверяет, было ли новое сообщение отправлено основным потоком.Однако в приложении Qt программа блокируется, как только она входит в главный цикл обработки событий в a.exec().Это предотвращает проверку занятого цикла и, следовательно, приводит к взаимоблокировке программы.

Так я порождаю рабочий поток графического интерфейса пользователя (на основе этого сообщения).

#include <thread>

// Start the Qt realtime plot demo in a worker thread
int argc = 0;
char **argv = NULL;
std::thread t1
        (
                [&] {
                    QApplication application(argc, argv);
                    MainWindow mainWindow;
                    mainWindow.show();
                    return application.exec();
                }
        );

1 Ответ

1 голос
/ 22 сентября 2019

Вы можете использовать собственные методы Qt для связи между потоками.Каждый объект Qt имеет сродство к потоку.Если вы создадите свой MainWindow объект в отдельном потоке GUI, он будет присоединен к этому потоку.Если вы используете сигналы и слоты Qt и соединяете их с Qt::QueuedConnection, слот будет вызываться в потоке объекта через основной цикл этого потока, независимо от того, откуда поступил сигнал.

Обратите внимание, что вы можетеопределять сигналы в классе MainWindow, но вызывать их извне, так как они являются общедоступными.Это означает, что вам не нужен отдельный отправляющий объект.В конструкторе MainWindow (например) вы можете подключить свой собственный сигнал к слоту или лямбда-методу.

Чтобы иметь возможность испускать сигнал MainWindow, вы можете иметь указатель MainWindow, установленный на nullptrвне потока GUI и установите этот указатель (через лямбда-захват) на новый объект, который вы создаете в потоке GUI.Вне вашей темы, когда вы хотите испустить сигнал, вы можете сделать что-нибудь.как if (mainWindow) mainWindow->signal(…).Я предполагаю, что вам все равно нужна проверка, поскольку ваш графический интерфейс не является обязательным.

Два примечания:

  1. Вы также можете отказаться от сигнала с помощью QMetaObject::invokeMethod, он удаляет шаблон, однако сигналы могут бытьподключается через ссылку на метод класса, который проверяется во время компиляции;Метод QMetaObject использует сопоставление строк во время выполнения.Также с общедоступными сигналами, но с защищенными слотами, вы можете быть уверены, что внешний код не вызывает случайно методы напрямую.
  2. Когда вы подключаете сигнал к лямбде, убедитесь, что вы указали принимающий объект.Тогда как connect(this, &MainWindow::signal, this, [this] {…}); будет выполнять лямбду в получающем потоке, connect(this, &MainWindow::signal, [this] {…}); будет , а не .
...