A
ArtisanТам. 22, 2020, 1:37 Т.Қ.

И вновь о потоках и moveToThread.

Qt

Для создания потоков я успешно использую подход moveToThread. Как и принято, при таком подходе, конструктор класса оставляем пустым (дабы не забываем что наш объект, который должен переместиться в поток, будет таки первоначально создан в основном (GUI) потоке. А всё что должно было быть выполнено конструктором, выполняем по сигналу &QThread::started. И на первый взгляд можно подумать, что теперь наш MyObj расположен в новом потоке, и далее можно о нём забыть и не беспокоиться. И действительно, все поля нашего объекта будут расположены в новом потоке. А вот теперь момент, на который в статьях почти нет никакого акцента. Где же будут выполняться методы, слоты MyObj который мы поместили в NewThread? После такого простого и действенного способа как moveToThread так и хочется подумать что будут выполняться в NewThread, и при использовании в QML, при реакции на какой-нибудь onClicked: MyObj.some_slot (допустим MyObj зарегистрировав через rootContext(), хотя можно и плагином через import, в вопросе потоков разницы никакой), мы можем и не ожидать что наш слот/метод всё равно будет проворачиваться в (GUI) потоке, а не как можно наскоро предположить, что во NewThread.
Для решения данной проблемы мне приходиться использовать класс посредника, Mediator, который так и остаётся "жить в GUI потоке", именно его мы регистрируем в QML контексте, и создаём цепочку через onClicked: Meditator.some_signal. И вот уже на стороне Mediator мы можем указать где выполнить слот MyObj, положив его в очередь используя Qt::ConnectionType::QueuedConnection или Qt::ConnectionType::AutoConnection.
Вот собственно и вопрос, есть ли способ на стороне QML сразу указывать что слот должен выполниться на стороне потока своего объекта, или еще каким-то образом обязать все методы, слоты объекта находящегося в NewThread запускать свои методы, слоты именно в своём потоке? Или так и придётся созавать цеочку: QML: onClicked - сигнал Mediator, далее на стороне C++:сигнал Mediator-слот MyObj с Qt::ConnectionType::QueuedConnection? А moveToThread по факту переносит только поля объекта в новый поток, а вся логика объекта так и будет проворачиваться в потоке, где объект был инициализирован?

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

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

5
Evgenii Legotckoi
  • Там. 24, 2020, 2:34 Т.Ж.

Проблема в том, что если объекту, который наследован от QObject не устанавливать parent, то QML обычно забирает права владения на этот объект, а это может ещё привести и к удалению сборщиком мусора. С другой стороны, сама по себе архитектура как Qt так и QML предполагает, что графические объекты обязаны обрабатываться в главном GUI потоке. То есть правильным подходом является перенос бизнес логики в отдельный потоки, но никак не GUI объектов.
То есть работать то может в каких-то случаях и будет, но не факт, что стабильно.

    A
    • Там. 24, 2020, 2:51 Т.Ж.

    Значит всё, что я регистрирую для QML через rootContext() или import, забирается QML (и не важно, что я переношу это в другой поток до этого). Но как тогда правильно выстроить процесс взаимодействия GUI (этот же onClicked) с MyObj, который должен полностью выполнять свою логику в другом потоке (объект отвечает за работу с аппаратурой). Как я описал, делаю через объект Mediator, который как раз и остаётся в GUI потоке. Думаю, мне нужно Ваше пояснение поподробнее о "правильным подходом является перенос бизнес логики в отдельный поток", как корректнее это сделать, чтобы я мог взаимодействовать из GUI с объектом, чья логика должна выполняться в отдельном потоке.

      Evgenii Legotckoi
      • Там. 24, 2020, 3:03 Т.Ж.
      • Жауап шешім ретінде белгіленді.

      Значит всё, что я регистрирую для QML через rootContext() или import, забирается QML (и не важно, что я переношу это в другой поток до этого)

      Полагаю, что да. Вот более подробное объяснение такой проблемы QML - Урок 023. Охота за багами при передаче указателя на QObject в QML . Там, конечно, не используется установка контекста, но уверен, что работать будет также, как и в статье описано.

      Я пока не до конца понял как именно вы используете медиатор, но полагаю, что наши мысли сходны, просто называем это по разному.

      Я бы сделал так, создаю объект, который через setContext переносится в QML, обычно у меня в таком случае всегда есть какой-то объект, класс которого называется AppCore , и он отвечает за бизнес логику. В данном классе есть методы, слоты, сигналы и т.д. которые вызываются в QML, через них же передаются в данный класс данные для обработки. И вот уже внутри AppCore есть уже другие классы, объекты которых я передаю в другие потоки через moveToThread . И уже эти классы будут обрабатывать всю бизнес логику внутри других потоков. А там уже AppCore будет управлять установкой значений и получений данных для обработки из QML.

      Полагаю, что я описал сейчас тот же самый ваш медиатор, но только с той разницей, что я не буду передавать объекты QML в C++. Я буду формировать данные, которые вводятся в объекты QML и уже их буду передавать в AppCore для дальнеёшей обработки в отдельных потоках.

      С QML есть ещё другие подводные камни в том плане, что там свой конвейер для отрисовки, и может быть дополнительное распарллеливание данных. Лично я не настолько много копался в исходниках QML, чтобы добровольно раскладывать вокруг себя грабли, поэтому и не стал бы пытаться дёргать QML объекты в другие потоки.

        A
        • Там. 24, 2020, 4:21 Т.Ж.

        Да, я поступаю также. AppCore (мой Meditator) пораждает все необходиме нам объекты, распределяет их по потокам, и вся обработка происходит в методах (слотах) этих объектов в своих потоках. Но выходит приходится создавать цепочки connect между AppCore и обрабатывающими объектами, с указанем Qt::ConnectionType::QueuedConnection или Qt::ConnectionType::AutoConnection иначе данные и логика могут оказаться в разных потоках. Вот и выходит длинная цепочка, которую я думал можно сокраить: из QML вызывать сигналы/слоты AppCore которые в свою очередь будут соединяться(или вызывать) слоты (обработчики) объектов-обработчиков, что живут уже в других потоках. P.S. Была крамольная идея убрать все эти цепочки, зарегистрировав внутренний для AppCore объект-обработчк (MyObj) через Q_PROPERTY и геттер, но в итоге лёгкая конструкция onCliced: AppCore.MyObj.slot_do_some() , как теперь ясно почему, запускалась в GUI потоке а не в потоке MyObj. Спасибо за ответ, значит я двигался в верном направлнении. Последний вопрос, для уточнения, часто встречал этот термин "бизнес логика" когда искал решение своего вопроса и работы с MVC (в нашем случае MVD, так как у нас Delegate) Зачем вводится новый термин для процесса обработки?

          Evgenii Legotckoi
          • Там. 24, 2020, 4:34 Т.Ж.

          Скорее это просто обобщённый термин для всего того, что скрыто от пользователя. В Случае MVC/MV - бизнес логика сидит в модели. В случае с медиатором, она сидит за медиатором (AppCore), который уже делегирует обработку данных в объекты, которые крутятся в других потоках. В случае с Web бизнес логика будет сидеть на бэкенде (особенно заметно, когда за бэкенд и фронтенд отвечают разные сервера).

            Пікірлер

            Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
            Кіріңіз немесе Тіркеліңіз
            OI
            • Ora Iro
            • Жел. 24, 2024, 6:38 Т.Ж.

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

            • Нәтиже:40ұпай,
            • Бағалау ұпайлары-8
            AD

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

            • Нәтиже:50ұпай,
            • Бағалау ұпайлары-4
            m
            • molni99
            • Қаз. 26, 2024, 1:37 Т.Ж.

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

            • Нәтиже:80ұпай,
            • Бағалау ұпайлары4
            Соңғы пікірлер
            ИМ
            Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
            Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
            Evgenii Legotckoi
            Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
            Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
            A
            ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
            Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
            ИМ
            Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
            Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
            d
            dblas5Шілде 5, 2024, 11:02 Т.Ж.
            QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
            Енді форумда талқылаңыз
            Evgenii Legotckoi
            Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
            добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
            t
            tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
            google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
            NSProject
            NSProjectМаусым 4, 2022, 3:49 Т.Ж.
            Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
            9
            9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
            Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

            Бізді әлеуметтік желілерде бақылаңыз