Russian Qt Forum
Ноябрь 22, 2024, 23:01
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
Процесс замерзает при работе интерфейса
Страниц: [
1
]
2
3
4
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Процесс замерзает при работе интерфейса (Прочитано 23025 раз)
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Процесс замерзает при работе интерфейса
«
:
Ноябрь 13, 2014, 00:24 »
Столкнулся со странным поведением при отладке трех взаимодействующих процессов. Бутерброд толстый, весь код нереально показать, проще в общем описать.
1я нить выполняется циклически и пихает в сигнал разнообразные данные, упакованные в QVariant - пока проверяю со строками, целыми и вещественными числами. Сигнал по определению Queued. Эта нить находится в отдельной загружаемой DLL.
В другой загружаемой DLL в пространстве "основного" процесса приложения находится приемник сигнала, который получает данные, распознает их тип, и запускает на выполнение 3ю нить, обрабатывающую по-разному данные разного типа. Причем запускает он её не простым стартом QThread, а снятием
ранее запущенной
нити, которая к этому времени находится в WaitCondition. То есть, основной процесс-приемник сигнала делает wakeOne() для ожидающей нити, после того, как разобрал данные и подготовил для обработки. И сразу, как только он разбудил обработчик, основной процесс приостанавливается на своём WaitCondition (иначе он начинает ловить следующие входящие сигналы, и начинается чехарда при подготовке данных, которые никто не успевает обработать). Когда обработка закончена, 3я нить снимает основной процесс с ожидания вызовом wakeOne() сама снова становится в WaitCondition, и приём повторяется.
Это всё очень славно работает, пока... не пошевелишь мышкой. Стоит это сделать - не понятно по какой причине интерфейс замерзает, но
не полностью
. Приложение реагирует на кнопку закрытия, причем не тупо закрывается, а нормально отрабатывает все заложенные функции (а там производится рассылка команды "умри" нескольким плагинам, которые еще и отвечают потом, что они умерли, и только после этого приложение закрывается - это всё выполняется). Более того, судя по потреблению процессора и посвистыванию дросселей материнки, 1я нить, которая отправляет данные, продолжает работать - очередь наполняется, свободная память при этом потихоньку исчезает. Ощущение такое, будто обрабатывающая нить ушла в WaitCondition, а основной процесс её почему-то оттуда не снимает. Совершенно точно нет состояния dead-lock - в нём приложение у меня нормально не закрывается, это проверенно. И при dead-lock в отладчике появляется соответствующее сообщение - тут его нет.
Причем всё это на не самом слабеньком процессоре с 4-мя ядрами...
Вот вопрос - кто-нибудь сталкивался с чем-то подобным? Когда отработка интерфейса "сбивает" работу слотов, в которых используются функции синхронизации с помощью WaitCondition? Я делал такие синхронизации несколько раз, но ни разу именно так, и ни разу не влипал в подобное. Буду, конечно, пытаться изменить логику, но интересно - может есть какие-то известные ограничения?
«
Последнее редактирование: Ноябрь 13, 2014, 00:27 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
vulko
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #1 :
Ноябрь 13, 2014, 09:30 »
В UI'ном трэде что-то делается?
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #2 :
Ноябрь 13, 2014, 10:45 »
в UI (я его назвал основным процессом) слот принимает сигнал, определяет тип, декодирует данные, кладет их на специальный стек (всё это очень быстро, сотня строк без тяжелых вызовов), будит нитку обработчика и становится в ожидание следующего сигнала - наверно, в последнем проблема, но странно, что пока мышкой не повозишь, всё нормально
«
Последнее редактирование: Ноябрь 13, 2014, 10:50 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
vulko
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #3 :
Ноябрь 13, 2014, 10:54 »
Цитата: Гурман от Ноябрь 13, 2014, 10:45
в UI (я его назвал основным процессом) слот принимает сигнал, определяет тип, декодирует данные, кладет их на специальный стек (всё это очень быстро, сотня строк без тяжелых вызовов), будит нитку обработчика и становится в ожидание следующего сигнала - наверно, в последнем проблема, но странно, что пока мышкой не повозишь, всё нормально
ну вот в этом то и проблема. выноси этот функционал за пределы UI'ного треда, а основной поток используй только для обновления интерфейса (отображения данных) и взаимодействия с пользователем.
даже если нет тяжелых вызовов, все равно есть ожидание. в этом и проблема. ожидание нельзя делать в UI'ном треде, т.к. помимо твоего кода там происходит много чего связанного с интерфейсом. Постоянные ивенты, перерисовки, апдейты и прочее прочее...
Записан
Bepec
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #4 :
Ноябрь 13, 2014, 10:57 »
Скорее всего у вас глушится UI поток сигналами.
Интерфейс замерзает - непонятное у вас описание.
То ли интерфейс у программы замерзает - она не реагирует на наведение/щелчки мышкой и прочее.
То ли у вас окно зависает - покрывается блюром и считается зависшим системой.
Но, думаю, что у вас просто где-то ошибка и/или всё же упущение количества вызовов.
Вот такие расплывчатые догадки в ответ на общее описание.
PS ++ к предыдущему оратору
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #5 :
Ноябрь 13, 2014, 11:12 »
Цитата: Bepec от Ноябрь 13, 2014, 10:57
Интерфейс замерзает - непонятное у вас описание.
То ли интерфейс у программы замерзает - она не реагирует на наведение/щелчки мышкой и прочее.
То ли у вас окно зависает - покрывается блюром и считается зависшим системой.
интерфейс не реагирует на нажатия и наведение, кроме кнопки закрытия окна (на неё реагирует), перерисовывается нормально
глушиться тестовыми сигналами UI не должен - они идут очень редко, специально с целью тестирования они посылаются каждые
полсекунды
, заглушить этим интерфейс невозможно
значит придется еще одну нить запускать, для приёма и декодирования сигналов - в нити обработчика это делать сложно, она физически в другой DLL находится, отлаженной, и написанной преимущественно на Си
Записан
2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #6 :
Ноябрь 13, 2014, 11:39 »
Да, проблема в ожидании в основном процессе. Убрал его и сделал передающий сигнал Blocking, интерфейс стал нормально работать.
Записан
2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #7 :
Ноябрь 13, 2014, 19:57 »
А шайтан... Если в QThread запустилась нитка, залочила некий мутекс, завершилась (но мутекс не разлочился), и потом снова запустилась (тот же объект QThread) - при повторном запуске, вместо dead-lock она в этом мутексе просто молча залипает. Объект тот же, но нитка другая, другой ThreadID. И разлочить после перезапуска этот мутекс не нельзя - слетает с ошибкой.
Что-то я не помню предупреждения об этом в документации, а просто так это не совсем очевидно.
Записан
2^7-1 == 127, задумайтесь...
Bepec
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #8 :
Ноябрь 13, 2014, 20:22 »
QMutexLocker используйте.
И насколько я помню, повторные локи всегда такое вызывали
Там где то строчка имеется что всегда нужно контролить мутекс, иначе будет ой ой ой.
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #9 :
Ноябрь 13, 2014, 21:11 »
Цитата: Bepec от Ноябрь 13, 2014, 20:22
QMutexLocker используйте.
не вполне понятно, чем он поможет, у меня нет необходимости синхронизировать мутекс с созданием и удалением чего либо, поскольку ничего не создается и не удаляется
Цитата: Bepec от Ноябрь 13, 2014, 20:22
И насколько я помню, повторные локи всегда такое вызывали
Там где то строчка имеется что всегда нужно контролить мутекс, иначе будет ой ой ой.
само собой, но речь не об этом, а о том, что при разных
последовательных
запусках
одного и того же
QThread::run() получаются
разные нити
, которые не могут работать с одним и тем же мутексом, также как если бы это была одна и та же нить - а проблема у меня именно в этом
Записан
2^7-1 == 127, задумайтесь...
Bepec
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #10 :
Ноябрь 13, 2014, 23:01 »
Локер поможет в том, что при завершении run автоматом разлочит мутекс. Он берёт контроль за его состоянием на себя ) и ваша проблема исчезает
PS это кстати поведение совершенно нормально. мой первый проект с потоками получал данные из контейнера давно удалённой нити
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #11 :
Ноябрь 13, 2014, 23:32 »
Цитата: Bepec от Ноябрь 13, 2014, 23:01
Локер поможет в том, что при завершении run автоматом разлочит мутекс. Он берёт контроль за его состоянием на себя ) и ваша проблема исчезает
В руководстве нет ничего про разлочивание мутекса локером при завершении run(). Там вообще не описано никакой связи между QThread и МутексЛокером.
«
Последнее редактирование: Ноябрь 13, 2014, 23:34 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
Bepec
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #12 :
Ноябрь 13, 2014, 23:42 »
QMutexLocker блочит мутекс в своем конструкторе и разлочивает в деструкторе. Потому создавая в начале run QMutexLocker вы получаете гарантию, что в конце у вас будет разлоченный мутекс
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: Процесс замерзает при работе интерфейса
«
Ответ #13 :
Ноябрь 13, 2014, 23:53 »
Цитата: Bepec от Ноябрь 13, 2014, 23:42
QMutexLocker блочит мутекс в своем конструкторе и разлочивает в деструкторе. Потому создавая в начале run QMutexLocker вы получаете гарантию, что в конце у вас будет разлоченный мутекс
Нет такой возможности. QThread::run() и мутекс находятся в разных DLL с ручной загрузкой, то есть, в плагинах. Более того, выполняемый в run() код находится в третьем плагине. Любой из плагинов может отсутствовать. Код, где мутекс и синхронизируемый код умеют общаться, но приплетать туда еще и run() будет идеологически неверно. Этот run ничего не знает и не иммет права знать о загруженных плагинах, и вообще выглядит вот так
Код:
void RunThread::run()
{
_main( argc, argv );
}
То есть, в той же нити, где мутекс лочится, негде разместить разлочивание, я над этим уже несколько часов голову ломаю. Я так понимаю, МутексЛокер не сработает, если его создать в одной нити, а удалить
из
другой? Собственно, должен случиться тот же ассерт, что и про попытке просто сделать лок и анлок мутекса в разных нитях.
«
Последнее редактирование: Ноябрь 14, 2014, 00:00 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
vulko
Гость
Re: Процесс замерзает при работе интерфейса
«
Ответ #14 :
Ноябрь 14, 2014, 09:26 »
Цитата: Гурман от Ноябрь 13, 2014, 23:53
Я так понимаю, МутексЛокер не сработает, если его создать в одной нити, а удалить
из
другой? Собственно, должен случиться тот же ассерт, что и про попытке просто сделать лок и анлок мутекса в разных нитях.
Мьютекс локер это критическая секция.
Работает в рамках внутри { }.
Это тот же
{
mutex.lock();
// do something
mutex.unlock();
}
Только немного удобнее, особенно если всякие if else с return'ами.
Лок анлок мьютекса в разных потоках делать не просто можно, а нужно.
Цитировать
не вполне понятно, чем он поможет, у меня нет необходимости синхронизировать мутекс с созданием и удалением чего либо, поскольку ничего не создается и не удаляется
мьютекс не только для синхронизации создания и удаления.
мьютекс для синхронизации по разделяемому ресурсу. при этом ресурс может на самом деле быть вообще статичным, т.е. не меняться.
идея в том, что залочив мьютекс в одном потоке, другие при попытке его залочить встанут в wait, до тех пор пока первый поток не разлочит мьютекс.
т.е. таким образом работа потоков превращается в последовательную, параллельная работа исключается.
можно комбинировать 2 и более мьютексов, тогда в каких то случаях потоки смогут работать парраллельно. в общем из мьютекса можно сообразить много всяких интересных штук.
Записан
Страниц: [
1
]
2
3
4
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
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 сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...