U
UrekMazin0Aug. 20, 2020, 2:19 p.m.

Работа с потоками с помощью 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. Тут крутое оформление сайта))
Фото кода, аккуратно, много мусора:

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

11
Алексей Внуков
  • Aug. 20, 2020, 3:21 p.m.

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

    U
    • Aug. 20, 2020, 3:50 p.m.
    • (edited)

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

      Алексей Внуков
      • Aug. 20, 2020, 4:10 p.m.
      • (edited)
      • The answer was marked as a solution.

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

        U
        • Aug. 20, 2020, 4:18 p.m.

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

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

          Алексей Внуков
          • Aug. 20, 2020, 4:28 p.m.

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

            Алексей Внуков
            • Aug. 20, 2020, 4:32 p.m.

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

              U
              • Aug. 20, 2020, 5:03 p.m.
              • (edited)

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

                Алексей Внуков
                • Aug. 20, 2020, 5:45 p.m.

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

                Q_DECLARE_METATYPE(cv::Mat)
                
                int main(int argc, char *argv[])
                {
                    ...
                    qRegisterMetaType<cv::Mat>("cv::Mat");
                    ...
                }
                
                  Ruslan Polupan
                  • Aug. 21, 2020, 1:08 a.m.

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

                    U
                    • Aug. 21, 2020, 7:56 a.m.
                    • (edited)

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

                      U
                      • Aug. 21, 2020, 7:57 a.m.

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

                        Comments

                        Only authorized users can post comments.
                        Please, Log in or Sign up
                        г
                        • ги
                        • April 23, 2024, 11:51 p.m.

                        C++ - Test 005. Structures and Classes

                        • Result:41points,
                        • Rating points-8
                        l
                        • laei
                        • April 23, 2024, 5:19 p.m.

                        C ++ - Test 004. Pointers, Arrays and Loops

                        • Result:10points,
                        • Rating points-10
                        l
                        • laei
                        • April 23, 2024, 5:17 p.m.

                        C++ - Тест 003. Условия и циклы

                        • Result:50points,
                        • Rating points-4
                        Last comments
                        k
                        kmssrFeb. 9, 2024, 3:43 a.m.
                        Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                        Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                        EVA
                        EVADec. 25, 2023, 7:30 p.m.
                        Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                        J
                        JonnyJoDec. 25, 2023, 5:38 p.m.
                        Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                        G
                        GvozdikDec. 19, 2023, 6:01 a.m.
                        Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                        Now discuss on the forum
                        G
                        GarApril 22, 2024, 1:46 p.m.
                        Clipboard Как скопировать окно целиком в clipb?
                        DA
                        Dr Gangil AcademicsApril 20, 2024, 3:45 p.m.
                        Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
                        a
                        a_vlasovApril 14, 2024, 2:41 p.m.
                        Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                        Павел Дорофеев
                        Павел ДорофеевApril 14, 2024, 10:35 a.m.
                        QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                        f
                        fastrexApril 4, 2024, 12:47 p.m.
                        Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

                        Follow us in social networks