Russian Qt Forum
Ноябрь 23, 2024, 07:51
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
Потоки и сообщения об ошибках
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Потоки и сообщения об ошибках (Прочитано 5343 раз)
Serr500
Гость
Потоки и сообщения об ошибках
«
:
Май 29, 2012, 20:39 »
Условие задачи. Имеется некоторое число потоков, которые условно назовём "потребителями" и один поток, который назовём "управляющим". Кроме того, в приложении есть поток, в котором находятся все графические элементы, условно назовём его "GUI-поток". "Потребители" в заранее неизвестные моменты времени могут генерировать сигнал ошибки, обработка которой зависит от ответа пользователя, т.е. должен появиться диалог, в котором пользователь нажмёт на одну из кнопок.
Что требуется. Требуется, чтобы "потребитель" приостановил своё выполнение на время обработки ошибки, т.е поток должен быть "заморожен" в той точке, откуда испускается сигнал, ни один оператор "потребителя" после сигнала не должен выполняться. Вместо испускания сигнала (emit) может использоваться вызов метода "управляющего", указатель на который можно передать "потребителю". Далее этот сигнал должен быть получен "управляющим" и передан в "GUI-поток", который выведет диалог. После выбора пользователем действия сигнал проходит по цепочке в обратном направлении, т.е. "управляющий" получает ответ от "GUI-потока", выполняет с ним некоторые действия и передаёт ответ (возможно, модифицированный) "потребителю", который продолжит свою работу. "Управляющий" поток блокироваться не должен, максимум - кратковременная блокировка на время выполнения некоторых методов, полной блокировки потока вплоть до ожидания ответа пользователя быть не должно, "управляющий" должен быть готов обработать в это время другие сигналы.
Ситуация осложняется тем, что потоки могут генерировать сигнал ошибки одновременно, т.е. один "потребитель" может сгенерировать сигнал в то время, как второй ещё не получил ответ пользователя (пользователь не нажал на кнопку). В такой ситуации сигнал должен быть помещён в очередь ("потребитель" должен оставаться в состоянии блокировки) и обработан только после того, как "управляющий" получит ответ пользователя (можно до того, как "управляющий" передаст ответ "потребителю", но в любом случае не ранее того, как получит ответ сам). Напомню, что "управляющего" блокировать на это время нельзя.
Собственно вопрос: как реализовать такое поведение? В выборе объектов синхронизации ограничений нет - можно использовать любые. Ограничение лишь одно - использовать только Qt и С++. "Потребители" - простые потомки QThread без очереди сообщений, "управляющий" - потомок QThread с собственной очередью сообщений.
Заранее спасибо за любые подсказки и конструктивные предложения.
Записан
alexis031182
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #1 :
Май 29, 2012, 20:50 »
Можно через семафоры.
В каждом "потребителе" объявить по семафору. Сразу после отправки сообщения для пользователя в GUI-поток (сообщение должно содержать указатель на семафор "потребителя") выполнить acquire() - "потребитель" заморозится. Как только GUI-поток отработает это сообщение, выполнить release() через полученный ранее указатель.
Записан
Serr500
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #2 :
Май 29, 2012, 20:58 »
Цитата: alexis031182 от Май 29, 2012, 20:50
Можно через семафоры.
...
О! Это мысль. Почему-то меня потянуло в сторону мьютексов, а там возникала вероятность того, что сигнал успеет обработаться до вызова QMutex::lock(). С семафорами такой ситуации не возникнет. Если не обработалось, то QSemaphore::acquire() "тормознёт" "потребителя", а если успело обработаться - то QSemaphore::release() уже увеличит счётчик семафора и acqire проскочит без блокировки.
Огромное спасибо. Эта идея идеально решает одну часть задачи. Остаётся вторая - обработка сигналов по очереди.
Записан
alexis031182
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #3 :
Май 29, 2012, 21:02 »
В гуи сообщения будут поступать по очереди. Их можно просто складировать в какой-нибудь контейнер и выполнять в гуи друг за другом, исходя из реакции пользователя. А семафоры не дадут своим соответствующим "потребителям" проснуться раньше времени.
Записан
Serr500
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #4 :
Май 29, 2012, 21:14 »
А как бы это получше реализовать? Контейнер-то тоже надо защищать от одновременных операций. После выполнения обработки нужно будет удалить сообщение из очереди, а "управляющий" в это время может попытаться в очередь добавить новое. Как бы не получить "мёртвую блокировку". И как сообщать GUI, что ему нужно обработать новое сообщение? Кинуть сигнал?
Записан
alexis031182
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #5 :
Май 29, 2012, 21:22 »
Можно отсылать события через postEvent() или сигналы через Qt::QueuedConnection. Тогда никаких блокировок контейнера делать не нужно (события появятся в гуи-потоке). В этих же событиях или сигналах и отправлять указатели на семафоры вместе с другими данными от "потребителя".
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Потоки и сообщения об ошибках
«
Ответ #6 :
Май 29, 2012, 21:23 »
А почему не задействовать тип соединения Qt::BlockingQueuedConnection? Оно вроде именно для этого и предназначено
Записан
alexis031182
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #7 :
Май 29, 2012, 21:26 »
Да, пожалуй лучше всего
Записан
Serr500
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #8 :
Май 29, 2012, 21:36 »
Цитата: Igors от Май 29, 2012, 21:23
А почему не задействовать тип соединения Qt::BlockingQueuedConnection? Оно вроде именно для этого и предназначено
Э-э-э... Тут проблема. Блокировка с "потребителя" снимется как только завершится выполнение слота в "управляющем". А он должен ещё будет передать сигнал дальше, в гуи. Но тогда надо блокировать и выполнение слота, т.е. тормозить "управляющего", а этого делать нельзя. Или как-то можно "разорвать" выполнение слота?
Цитата: alexis031182 от Май 29, 2012, 21:22
Можно отсылать события через postEvent() или сигналы через Qt::QueuedConnection. Тогда никаких блокировок контейнера делать не нужно (события появятся в гуи-потоке). В этих же событиях или сигналах и отправлять указатели на семафоры вместе с другими данными от "потребителя".
Так... Приблизительно понятно... То есть "потребитель" испускает сигнал (или вызывает метод "управляющего") и ждёт освобождения семафора. "Управляющий" помещает сигнал в очередь и испускает свой сигнал, который ловится в ГУИ. ГУИ обрабатывает сигнал и кидает свой с результатом операции "управляющему". Тот, в свою очередь, обрабатывает сигнал и освобождает семафор "потребителя". Я правильно понял последовательность действий?
Записан
alexis031182
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #9 :
Май 29, 2012, 21:48 »
Цитата: Serr500 от Май 29, 2012, 21:36
Э-э-э... Тут проблема. Блокировка с "потребителя" снимется как только завершится выполнение слота в "управляющем". А он должен ещё будет передать сигнал дальше, в гуи. Но тогда надо блокировать и выполнение слота, т.е. тормозить "управляющего", а этого делать нельзя. Или как-то можно "разорвать" выполнение слота?
Метод с блокирующим сигналом эффективен, если можно обойтись без "управляющего".
Цитата: Serr500 от Май 29, 2012, 21:36
Так... Приблизительно понятно... То есть "потребитель" испускает сигнал (или вызывает метод "управляющего")
"Потребитель" и "управляющий" находятся в разных потоках, и если предполагается использовать контейнер событий именно в "управляющем", то нужно либо неблокирующее событие (QCoreApplication::postEvent), либо неблокирующий сигнал (Qt::QueuedConnection).
Цитата: Serr500 от Май 29, 2012, 21:36
и ждёт освобождения семафора. "Управляющий" помещает сигнал в очередь и испускает свой сигнал, который ловится в ГУИ. ГУИ обрабатывает сигнал и кидает свой с результатом операции "управляющему". Тот, в свою очередь, обрабатывает сигнал и освобождает семафор "потребителя". Я правильно понял последовательность действий?
Да, правильно. Если "управляющий" обязателен, то именно так.
Записан
Serr500
Гость
Re: Потоки и сообщения об ошибках
«
Ответ #10 :
Май 29, 2012, 22:06 »
Цитата: alexis031182 от Май 29, 2012, 21:48
Метод с блокирующим сигналом эффективен, если можно обойтись без "управляющего".
К сожалению, нельзя. Именно "управляющий" в итоге решает, какой ответ получит "потребитель". Он принимает решения не только на основании ответа пользователя, но и учитывает некоторые другие факторы. Например, он получает сигналы от ещё одного потока - "производителя". Архитектура такова, что "управляющий" нужен. Может быть, удастся его объединить с "GUI-потоком", но это другой вопрос. Пока не знаю, удастся ли это сделать. Не хочется оказаться в ситуации "заморозки" пользовательского интерфейса. Хотя "управляющего" крайне нежелательно блокировать, всё же его блокировка возможна и менее заметна, чем блокировка ГУИ.
Цитата: alexis031182 от Май 29, 2012, 21:48
"Потребитель" и "управляющий" находятся в разных потоках, и если предполагается использовать контейнер событий именно в "управляющем", то нужно либо неблокирующее событие (QCoreApplication::postEvent), либо неблокирующий сигнал (Qt::QueuedConnection).
Наверное, контейнер лучше оставить у "управляющего". Мне кажется, это более логично. ГУИ достаточно уметь только выводить окошко и сообщать результат. А обработка очереди сообщений об ошибках логичнее смотрится в управляющем потоке.
Спасибо всем за подсказки. Завтра попробую всё это реализовать в коде. Но если есть ещё какие-либо предложения, буду очень рад их увидеть.
Записан
Страниц: [
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 сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...