U
UrekMazin020 серпня 2020 р. 14:19

Работа с потоками с помощью QtConcurentRun

C++, OpenCV, Qt, QtConcurrent

Доброе время суток. Создаю pet-project. Суть программы в визуализации функций OpenCV. Работа будет вестись с псевдо-видео с камеры.
По кнопке Start стартует функция, в которой проходит работа с классом OpenCV и отрисовка картинки с камеры на QLabel. Отрисовка происходит в бесконечном цикле while(isRun). Очевидно что он забирает на себя основной поток, после чего весь виджет зависал и кнопка Stop {isRun=false} была бесполезна. Стало очевидно что программу нужно делать многопоточной, ибо от while никак не отказаться.

Мне подсказали сделать так:

По кнопке старт 
    isRun = true;
    QtConcurrent::run([this]{
        while(isRun)
        {
            static int count = 0;
            ...
            qDebug() << "task: " << (count++);
        }
    });
По кнопке стоп
   isRun = false;

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

 По кнопке старт 
    isRun = true;
    QtConcurrent::run([this]{
        while(isRun)
        {
            static int count = 0;
            ...
            qDebug() << "task: " << (count++);
        }
        qDebug() << "One" << endl;   // ДОБАВЛЕНО
    });
    QDebug() << "Two" << endl;       // ДОБАВЛЕНО

По кнопке старт выводится Two, на стоп One

Объясните пожалуйста, как работает функция QtConcurrent::run, и почему числа выводятся в такой последовательности. Будет круто если дадите ссылку на хорошие статьи об QtConcurrent, я к сожалению не нашёл даже на английском. Ещё лучше если скажете как сделать что бы "Start" работал больше одного раза =-)
UPD. Тут крутое оформление сайта))
Фото кода, аккуратно, много мусора:

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

11
Алексей Внуков
  • 20 серпня 2020 р. 15:21

я делал чуть по другому, в отдельном потоке запускал цикл обработки камеры, а потом каждый фрейм cv::Mat отправлял сигналом в нужные потоки (один поток выводил видео, второй делал обработку видео).
а QtConcurrent::run не предназначен для бесконечного цикла, он для обработки какого-то временного процесса, результат которого вам понадобится, наприме есть сложное математическое вычисление которое занимает время и ресурсы, для того чтоб сделать разово вычисление в другом потоке не целесообразно под него выделять целый тред, поэтому для него существует QtConcurrent::run, который создаст поток выполнит функцию, вернет значение и закроет поток

    U
    • 20 серпня 2020 р. 15:50
    • (відредаговано)

    Понял, спасибо. У вас не осталось проекта на гитхабе, где можно будет прочитать код с правильной реализацией? Если проект был коммерческим и вы не можете его показать, то я пойму. Каким способом вы реализовали потоки?

      Алексей Внуков
      • 20 серпня 2020 р. 16:10
      • (відредаговано)
      • Відповідь була позначена як рішення.

      та там показывать особо нечего, просто найти нужно. все по класике делаем рабочий класс, через QThread создаем поток, обьект класса делаем moveToThread. в отдельной функции делаем потоку старт, в конекте пишем что по сигналу от потока started, запускаем в рабочем класе функцию с бесконечным циклом получения кадров с камеры, каждый новый кадр через сигнал отправляем в нужное место, в параметре сигнала указываем cv::Mat,для корректной работы сигналов и чтоб не было адцкой загрузки проца в конце бесконечного цикла добавляем qApp->processEvents(); и QThread::msleep(10);
      п.с. в общем и все. пишите пробуйте, если что спрашивайте. вот как работать с потоками QThread , только учитите сейчас правильным считается делать moveToThread, по ссылке есть старый способ переопределение run(), и наследование от QThread - но это не правильно и морально устарело.

        U
        • 20 серпня 2020 р. 16:18

        Если я вас понял, правильным считается создание потока QThread и последующее moveToThread, а не наследование от QThread и переопределение run.

        Спасибо, благодаря вам понял свою проблему. Буду писать и пробовать :-)

          Алексей Внуков
          • 20 серпня 2020 р. 16:28

          да, поняли правильно

            Алексей Внуков
            • 20 серпня 2020 р. 16:32

            и не забудьте cv::Mat зарегистрировать как тип данных, иначе приложение может падать во время сигнала и в описании ошибки будет вам говорить что cv::Mat нужно зарегистрировать

              U
              • 20 серпня 2020 р. 17:03
              • (відредаговано)

              Извините что опять спрашиваю, а что подразумевается под "зарегестрировать переменную "? Этот момент не очень ясен

                Алексей Внуков
                • 20 серпня 2020 р. 17:45

                cv::Mat это не тип данных Qt, а opencv, поэтому Qt не знает о нем. чтоб нормально работали сигналы/слоты с не стандартными типами нужно их зарегистрировать. для этого в main:

                Q_DECLARE_METATYPE(cv::Mat)
                
                int main(int argc, char *argv[])
                {
                    ...
                    qRegisterMetaType<cv::Mat>("cv::Mat");
                    ...
                }
                
                  Ruslan Polupan
                  • 21 серпня 2020 р. 01:08

                  Может это вам поможет https://evileg.com/ru/post/424/

                    U
                    • 21 серпня 2020 р. 07:56
                    • (відредаговано)

                    Да, спасибо, как наглядный пример очень даже

                      U
                      • 21 серпня 2020 р. 07:57

                      Спасибо, действительно помогло

                        Коментарі

                        Only authorized users can post comments.
                        Please, Log in or Sign up
                        sf

                        C++ - Тест 004. Указатели, Массивы и Циклы

                        • Результат:90бали,
                        • Рейтинг балів8
                        МВ

                        Qt - Тест 001. Сигналы и слоты

                        • Результат:68бали,
                        • Рейтинг балів-1
                        ЛС

                        C++ - Тест 001. Первая программа и типы данных

                        • Результат:53бали,
                        • Рейтинг балів-4
                        Останні коментарі
                        A
                        ALO1ZE19 жовтня 2024 р. 05:19
                        Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                        ИМ
                        Игорь Максимов05 жовтня 2024 р. 04:51
                        Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                        d
                        dblas505 липня 2024 р. 08:02
                        QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                        k
                        kmssr08 лютого 2024 р. 15:43
                        Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                        АК
                        Анатолий Кононенко04 лютого 2024 р. 22:50
                        Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                        Тепер обговоріть на форумі
                        J
                        JacobFib17 жовтня 2024 р. 00:27
                        добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
                        ИМ
                        Игорь Максимов03 жовтня 2024 р. 01:05
                        Реализация навигации по разделам Спасибо Евгений!
                        JW
                        Jhon Wick01 жовтня 2024 р. 12:52
                        Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
                        КГ
                        Кирилл Гусарев27 вересня 2024 р. 06:09
                        Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
                        F
                        Fynjy22 липня 2024 р. 01:15
                        при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                        Слідкуйте за нами в соціальних мережах