Russian Qt Forum
Ноябрь 22, 2024, 06:57
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
QEventLoop и потоки
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: QEventLoop и потоки (Прочитано 12139 раз)
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 сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...