Название: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 01, 2016, 00:41 Доброго времени суток!
По роду своей деятельности я практически не сталкивался с разработкой многопоточных приложений, но теперь пришлось. Задача следующая. Пишу программу, которая занимается обработкой видеопотока в режиме реального времени. Первая часть программы представляет собой Web-сервер (за основу взял QtWebApp), вторая - модуль обработки видеопотока. Удаленный клиет шлет на Веб-сервер запросы типа начать обработку видеопотока, закончить обработку видеопотока, получить текущие данные по обработке. Я хотел сделать так, чтобы при получении запроса на начало обработки запускался бы модуль обработки в отдельном потоке и работал бы до получения сигнала об окончании или при окончании видеопотока. Не могу понять, как это можно реализовать по уму. Название: Re: Вопрос ламера о реализации многопоточности Отправлено: qate от Декабрь 01, 2016, 09:10 почитать для ознакомления https://wiki.qt.io/Threads_Events_QObjects, можно еще "Энтони Уильямс - Параллельное программирование на С++ в действии"
пришли данные на обработку - кинуть их событием в поток пришел сброс - кинуть событие в поток поток завершил работу - событие об окончании Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 11:38 В общем, где-то я с потоками таки накосячил. Как у меня сейчас все устроено. Запуск http-сервера:
Код: int main(int argc, char *argv[]) Вот код маппера запросов: Код: void RequestMapper::service(HttpRequest& request, HttpResponse& response) { Код: void StartController::service(HttpRequest &request, HttpResponse &response) { Оба потока нормально стартуют и работают, НО возникает ОЧЕНЬ большая проблема. Когда worker посылает сигнал getDataSignal, то impworker его не ловит и, соответственно, не может переслать данные в worker. Я подозреваю, что это связано с тем, что потоки создаются внутри StartController::service(HttpRequest &request, HttpResponse &response), но как выйти из этого положения я не представляю... Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 11:44 В дебаг ничего не выдает? А impworker чем занят все время? Может, он просто не дает прокрутиться очереди событий?
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 11:46 В дебаг ничего не выдает? А impworker чем занят все время? Может, он просто не дает прокрутиться очереди событий? Об этом я не подумал... impworker в это время занимается в цикле чтением и обработкой видеопотока. Может, он и тормозит очередь. А можно ли это как-то подталкивать периодически?Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 11:53 Наверное, у него просто некорректное чтение или обработка. Если читаются данные из файла через сигнал readyRead, то сигналы будут приходить. Надо код посмотреть, чтобы понять.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 11:55 Вот основной цикл impworker:
Код: while(1) capture читает фреймы из rtmp-потока. Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 11:57 Собственно, как я и предполагал - очередь событий тут не проталкивается. Почему бы тебе из этого класса не кидать сигнал с картинкой?
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 12:01 Собственно, как я и предполагал - очередь событий тут не проталкивается. Почему бы тебе из этого класса не кидать сигнал с картинкой? Ты имеешь ввиду не писать тут в файл, а в каком-нибудь другом потоке?Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 12:04 Нет, я имею ввиду не кидать сигнал getDataSignal из вокера, пусть вокер ждет сигналов от impworker
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 12:06 Нет, я имею ввиду не кидать сигнал getDataSignal из вокера, пусть вокер ждет сигналов от impworker В принципе, можно попробовать по таймеру кидать... Сейчас попробую...Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 12:10 Зачем по таймеру? Получил/обработал/кинул.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 12:26 Зачем по таймеру? Получил/обработал/кинул. Там какая фигня. На изображении подсчитываются объекты, количество которых Worker записывает в базу данных. Если посылать сигнал после каждого найденного объекта, то тормоза будут. Но, тем не менее, с таймером тоже не покатило. Сделал так:Код: QTimer *timer = new QTimer(this); Код слота: Код: void ImageProcessingWorker::prepareCounters() В итоге worker получает все накопившиеся сигналы только после остановки потока impworker Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 12:35 Опять ты неверно мыслишь. :) У тебя таймер не будет срабатывать, ибо нет обработки очереди сообщений. Тебе нужно явно кидать сигнал внутри while.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 12:44 Опять ты неверно мыслишь. :) У тебя таймер не будет срабатывать, ибо нет обработки очереди сообщений. Тебе нужно явно кидать сигнал внутри while. QCoreApplication::instance()->processEvents() внутри while спасло отца русской демократии ;DНазвание: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 12:54 Опять ты неверно мыслишь. :) У тебя таймер не будет срабатывать, ибо нет обработки очереди сообщений. Тебе нужно явно кидать сигнал внутри while. QCoreApplication::instance()->processEvents() внутри while спасло отца русской демократии ;DНазвание: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 13:43 Опять ты неверно мыслишь. :) У тебя таймер не будет срабатывать, ибо нет обработки очереди сообщений. Тебе нужно явно кидать сигнал внутри while. QCoreApplication::instance()->processEvents() внутри while спасло отца русской демократии ;DНазвание: Re: Вопрос ламера о реализации многопоточно Отправлено: Пантер от Декабрь 09, 2016, 13:48 Псевдокот.
Код
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 09, 2016, 14:04 Ok, сейчас попробую
Название: Re: Вопрос ламера о реализации многопоточно&# Отправлено: Hvzh от Декабрь 09, 2016, 14:13 Псевдокот. Спасибо, работает. Правда, в if заменил time.start на time.restartКод
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 14:33 Это был псевдокот, писал по памяти. :)
Название: Re: Вопрос ламера о реализации многопоточно&# Отправлено: Igors от Декабрь 09, 2016, 15:02 Псевдокот. Код
Цитировать Уж больно ты щедрый, председатель, на колхозное добро (классика советского кино)Название: Re: Вопрос ламера о реализации многопоточно&# Отправлено: Авварон от Декабрь 09, 2016, 15:20 Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 15:22 Вот докопались, я вообще в данный момент на пыхе пишу.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Авварон от Декабрь 09, 2016, 15:37 Оно и видно ;D
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 09, 2016, 15:38 Не надо смеяться над вынужнденным пыхером. :(
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 12:53 Еще раз прошу помощи! Опять возникла проблема с сигналами. Я создаю потоки следующим образом:
Код: dbthread = new QThread; Строка Код: connect(impworker, SIGNAL(newCameraOpened(int)), this, SLOT(cameraStarted(int))); В потоке посылается сигнал: Код: void ImageProcessingWorker::process() однако в пункт назначения сигнал не приходит. И вообще непонятно, уходит ли... Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 13:17 Добавь вывод qDebug () в месте выдачи сигнала и в слоте.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 13:25 В слоте есть, также qDebug есть в createNewDbLine, то есть, перед сигналом. В слоте ничего не выводится, с createNewDbLine все нормально
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 13:37 Есть варианты:
1. У тебя источник и приемник получаются в одном потоке и этот поток занят. 2. Поток приемника занят. Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 13:44 Думаю, скорее второе... Буду проверять. Сейчас у меня вот так. После старта потоков начинается ожидание ответа от потока, оформленное в виде бесконечного цикла:
Код: for(;;) Значение cameraID должно менятся в слоте, который выглядит вот так: Код: void StartController::cameraStarted(int id) Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 13:55 Блин, конечно из-за цикла. Зачем тебе цикл нужен?
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 14:01 Вот полная функция:
Код: void StartController::service(HttpRequest &request, HttpResponse &response) { Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 14:06 Код
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 14:08 Если у тебя Qt5 и 11 стандарт, лучше лямбду вместо слота заюзать.
Код
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 14:14 Сейчас попробую...
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 14:26 Ура, работает. Еще одно огромное спасибо!
Название: Re: Вопрос ламера о реализации многопоточно Отправлено: Hvzh от Декабрь 14, 2016, 14:38 Ну, и до кучи еще один вопрос. Есть функция отключения камеры, которая принимает оь браузера один параметр - ID камеры. Сейчас она выглядит так:
Код: void StopController::service(HttpRequest &request, HttpResponse &response) { Остановка сейчас сделана через глобальную переменную procToKill. Это работает, но вариант совершенно неподходящий при большом количестве подключений. При этом функция о процессах ничего, кроме переданного ID не знает. Я могу послать сигнал, например, stopCamera(cameraID), но как мне ответ поймать? И как заставить impworker этот сигнал ловить? Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 14:50 У тебя каждая камера это отдельный процесс? Храни мапу соответствия номера камеры и номера процесса. Или я тчо-то не так понял.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 14:59 Каждая камера - отдельный поток
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 15:01 Храни где-нибудь мапу соответствия.
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 15:11 Храни где-нибудь мапу соответствия. Ну, могу я получить ИД потока, но он же, вроде, для внутреннего пользования, и остановить поток используя Thread ID вроде нельзяНазвание: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 15:22 QMap<int, QThread*> threads;
Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Пантер от Декабрь 14, 2016, 15:23 А еще лучше:
QMap<int, YouClass*> m; m->stop(); Название: Re: Вопрос ламера о реализации многопоточности Отправлено: Hvzh от Декабрь 14, 2016, 18:21 А еще лучше: Сделал так. Работает. Еще раз огромное спасибо!QMap<int, YouClass*> m; m->stop(); |