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
                        AD

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

                        • Результат:50бали,
                        • Рейтинг балів-4
                        m
                        • molni99
                        • 26 жовтня 2024 р. 01:37

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

                        • Результат:80бали,
                        • Рейтинг балів4
                        m
                        • molni99
                        • 26 жовтня 2024 р. 01:29

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

                        • Результат:20бали,
                        • Рейтинг балів-10
                        Останні коментарі
                        ИМ
                        Игорь Максимов22 листопада 2024 р. 11:51
                        Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                        Evgenii Legotckoi
                        Evgenii Legotckoi31 жовтня 2024 р. 14:37
                        Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                        A
                        ALO1ZE19 жовтня 2024 р. 08:19
                        Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                        ИМ
                        Игорь Максимов05 жовтня 2024 р. 07:51
                        Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                        d
                        dblas505 липня 2024 р. 11:02
                        QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                        Тепер обговоріть на форумі
                        Evgenii Legotckoi
                        Evgenii Legotckoi24 червня 2024 р. 15:11
                        добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                        t
                        tonypeachey115 листопада 2024 р. 06:04
                        google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                        NSProject
                        NSProject04 червня 2022 р. 03:49
                        Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                        9
                        9Anonim25 жовтня 2024 р. 09:10
                        Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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