Russian Qt Forum
Апреля 04, 2025, 14:18
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
QEventLoop и потоки
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: QEventLoop и потоки (Прочитано 12608 раз)
DarkHobbit
Самовар
Offline
Сообщений: 197
QEventLoop и потоки
«
:
Марта 31, 2020, 20:14 »
Доброго времени суток.
Я обрабатываю массивы данных, поступающие периодическими блоками. Обработка довольно "тяжёлая", стоит проблема быстродействия. Но каждый блок состоит из нескольких подблоков, которые можно обрабатывать независимо. Я решил этим воспользоваться и распараллелить вычисления.
Есть класс-обработчик. Есть класс-менеджер, который создаёт несколько обработчиков, и каждый из них перемещает (moveToThread) в отдельную QThread. По поступлении блока менеджер рассылает обработчикам сигналы начать обработку. По окончании обработки обработчики шлют сигналы об окончании.
Менеджер в начале работы создал объект loop класса QEventLoop. У него есть функция process(), которая вызывается по получении блока. Разослав обработчикам сигналы начинать, process() вызывает loop.exec(). Слот менеджера, принимающий сигналы об окончании обработки, проверяет, все ли обработчики "отписались", и если да - вызывает loop.exit(). После этого process() возвращает управление вызвавшей программе.
Экспериментальная проверка показала следующее.
Случай 1. Менеджер находится в основном потоке GUI-программы. Всё работает прекрасно, замеры показывают, что на 4-ядерном процессоре время обработки уменьшается в 3 с небольшим раза, что полностью согласуется с так называемым здравым смыслом. Здесь вопросов нет.
Случай 2, тяжёлый. Менеджер находится внутри DLL, которую вызывает внешняя программа. Причём поскольку у внешней программы есть чем заняться и без моей DLL, вызов происходит уже НЕ в основном потоке. Выхода из loop не происходит. Отладка показывает, что exit() в слоте вызывается, но выхода из exec() в process() я не вижу.
Я пока склонен винить вызывающую программу, но претензию сформулировать толком не могу. Вообще, может ли работать описанная схема, если QEventLoop организован не в главном потоке программы? Какие ещё подводные камни с QEventLoop возможны?
P.S. Да, есть ещё QtConcurrent, который, похоже, специально создан для таких вещей, но прежде чем хвататься за него, хотелось бы понять, почему не работает "низкоуровневый" способ. А то мне интуиция подсказывает, что если результат так разительно зависит от "внешних" факторов, то и QtConcurrent может не спасти.
P.P.S Проверено на Qt 4.7 и 4.8 под Windows 7 и Debian Stretch соответственно. Да, "энтерпрайз-старьё". Призывы мигрировать на Qt5 рассматриваются, но только в том случае, если у вас есть реальный опыт с отличием работы QEventLoop на разных мажорных версиях, а не просто "все нормальные пацаны сидят на последней версии".
«
Последнее редактирование: Марта 31, 2020, 20:34 от DarkHobbit
»
Записан
Мои проекты на Qt:
DoubleContact
,
LInvert
qate
Супер
Offline
Сообщений: 1177
Re: QEventLoop и потоки
«
Ответ #1 :
Марта 31, 2020, 21:21 »
думаю минимальный рабочий пример помог бы разобраться в проблеме
Записан
DarkHobbit
Самовар
Offline
Сообщений: 197
Re: QEventLoop и потоки
«
Ответ #2 :
Апреля 01, 2020, 10:53 »
qate
, я в курсе. Но вот в данном случае тяжеловато его сделать, такой пример. Особенно с учётом того, как раз в "минимальных" условиях всё прекрасно работает...
Записан
Мои проекты на Qt:
DoubleContact
,
LInvert
qate
Супер
Offline
Сообщений: 1177
Re: QEventLoop и потоки
«
Ответ #3 :
Апреля 01, 2020, 18:29 »
Цитата: DarkHobbit от Апреля 01, 2020, 10:53
qate
, я в курсе. Но вот в данном случае тяжеловато его сделать, такой пример. Особенно с учётом того, как раз в "минимальных" условиях всё прекрасно работает...
а в чем сложность - вместо тяжелой работы sleep поставить, не ?
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: QEventLoop и потоки
«
Ответ #4 :
Апреля 02, 2020, 11:24 »
Цитата: DarkHobbit от Марта 31, 2020, 20:14
Отладка показывает, что exit() в слоте вызывается, но выхода из exec() в process() я не вижу.
Не берусь утверждать что "именно так" (для не главной нитки), но "вполне возможно". Поковырявшись в отладчике можно сказать точно, но не лучше ли обойтись без "своего" EventLoop? Вторичный луп всегда добавит проблем, пусть решаемых. Напр создать "нитку упр-я" и поместить Ваш process в ее run. Или даже точнее - если текущая нитка не главная, то просто запустить process. Да, нитка будет ждать пока все отработает, но, как я понял, это устраивает.
A QtConcurrent работать должен. Как и QThreadPool который мне нравится больше.
Записан
DarkHobbit
Самовар
Offline
Сообщений: 197
Re: QEventLoop и потоки
«
Ответ #5 :
Апреля 03, 2020, 12:06 »
Цитата: Igors от Апреля 02, 2020, 11:24
QThreadPool который мне нравится больше.
Почему, кстати, если не секрет?
Записан
Мои проекты на Qt:
DoubleContact
,
LInvert
Авварон
Джедай : наставник для всех
Offline
Сообщений: 3260
Re: QEventLoop и потоки
«
Ответ #6 :
Апреля 03, 2020, 12:22 »
Цитата: DarkHobbit от Апреля 03, 2020, 12:06
Почему, кстати, если не секрет?
Потому что Igors любит голые указатели и не любит всё что сложнее голого указателя=)
Записан
DarkHobbit
Самовар
Offline
Сообщений: 197
Re: QEventLoop и потоки
«
Ответ #7 :
Апреля 03, 2020, 21:17 »
Цитата: qate от Апреля 01, 2020, 18:29
а в чем сложность - вместо тяжелой работы sleep поставить, не ?
sleep() вместо организации QEventLoop? Его ж, как я понимаю, принудительно не разбудишь? Отвёл ему 200 миллисекунд - он все 200 и будет ждать?
Нет, можно пойти по такому пути. Но тогда надо очень тщательно выбирать время усыпления. И либо process() будет на себя отнимать драгоценное процессорное время, либо часть блоков будет просто теряться. А время обработки подблока, к сожалению, плавает в зависимости от содержимого самого подблока...
Записан
Мои проекты на Qt:
DoubleContact
,
LInvert
qate
Супер
Offline
Сообщений: 1177
Re: QEventLoop и потоки
«
Ответ #8 :
Апреля 04, 2020, 09:46 »
sleep() для имитации "тяжелой нагрузки"
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: QEventLoop и потоки
«
Ответ #9 :
Апреля 04, 2020, 11:05 »
Цитата: DarkHobbit от Апреля 03, 2020, 12:06
Почему, кстати, если не секрет?
Выглядит более естественно
Цитата: Авварон от Апреля 03, 2020, 12:22
Потому что Igors любит голые указатели и не любит всё что сложнее голого указателя=)
Ну в общем да
Возвращаясь к теме. Вы создаете вторичный EventLoop, не то чтобы это "преступление", но не вызывается необходимостью, а значит надо признать что "велик" (костыль и.т.п). Ну и получаете проблемы которые хотите решать. Не вижу что мешает делать Ваш process прямо в вызывающей нитке. Раздача заданий и получение ответов - операции не трудоемкие. Если это не так - создать еще нитку упр-я
Записан
DarkHobbit
Самовар
Offline
Сообщений: 197
Re: QEventLoop и потоки
«
Ответ #10 :
Июня 09, 2020, 14:24 »
В общем, мне очень стыдно, но загвоздка была банально во флаге, взводящемся в неправильном месте. Просто на вариант 1 это не влияло, а во 2 варианте события об окончании обработки начинали приходить ещё до того, как основной поток осознал, что эта самая обработка началась.
Приношу извинения всем, кого напряг по тупому (как выяснилось) вопросу.
Записан
Мои проекты на Qt:
DoubleContact
,
LInvert
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...