Название: Высылка сигнала из потока Отправлено: markie от Февраль 20, 2013, 20:59 Всем привет! Не могу понять, почему сигналы из потока (не основного) не высылаются на каждой итерации цикла? Например, есть следующий код:
Код: while (1) И сигналы progress, которые должны были высылаться на каждой итерации, доходят до основного потока только после выхода из цикла. Может быть кто-нибудь знает, с чем это может быть связано? P.S. Код выноситься в отдельный поток с помощью moveToThread, наследования от QThread нет. Название: Re: Высылка сигнала из потока Отправлено: ViTech от Февраль 20, 2013, 21:27 Threads and QObjects (http://qt-project.org/doc/qt-4.8/threads-qobject.html), в частности "Signals and Slots Across Threads". Чтобы основной поток обработал события, после emit progress() нужно вызвать QCoreApplication::processEvents. Только надо подумать, надо ли так часто основной поток дергать.
Название: Re: Высылка сигнала из потока Отправлено: Igors от Февраль 21, 2013, 12:43 Threads and QObjects (http://qt-project.org/doc/qt-4.8/threads-qobject.html), в частности "Signals and Slots Across Threads". Чтобы основной поток обработал события, после emit progress() нужно вызвать QCoreApplication::processEvents. Только надо подумать, надо ли так часто основной поток дергать. По-моему QCoreApplication::processEvents будет извлекать события из EventLoop текущего потока. А если главная нитка висит на своем EventLoop, то зачем еще processEvents? Вот если по каким-то причинам while крутится в главной нитке - получится именно описанный эффект. Это легко проверить напечатав QThread::currentThreadId в главной нитке и while Название: Re: Высылка сигнала из потока Отправлено: ViTech от Февраль 21, 2013, 13:13 По-моему QCoreApplication::processEvents будет извлекать события из EventLoop текущего потока. А если главная нитка висит на своем EventLoop, то зачем еще processEvents? Мы не знаем, что там в каком потоке происходит, и какими сигналами связаны. Вот пусть автор темы и разберется как работают потоки, как между ними сообщения проходят, и что делать, если "сигналы доходят до основного потока только после выхода из цикла".Судя по Цитировать P.S. Код выноситься в отдельный поток с помощью moveToThread, наследования от QThread нет. его еще много интересных открытий ожидает :).Название: Re: Высылка сигнала из потока Отправлено: twp от Февраль 21, 2013, 14:54 И сигналы progress, которые должны были высылаться на каждой итерации, доходят до основного потока только после выхода из цикла. Может быть кто-нибудь знает, с чем это может быть связано? P.S. Код выноситься в отдельный поток с помощью moveToThread, наследования от QThread нет. Цитата: Assistant void QThread::run () [virtual protected] В exec() происходит отсылка сигналов. То получается что цикл крутится, а сигналы накапливаются в очереди. Как только цикл завершается, exec() отрабатывает и заваливает сигналами основной поток :)The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec(). Название: Re: Высылка сигнала из потока Отправлено: markie от Февраль 21, 2013, 15:03 QCoreApplication::processEvents - это какой-то грязный хак в моей ситуации.
Что нужно сделать: из потока, который занимается какой-либо длительной операцией, нужно управлять прогрессбаром. Соответственно, первое, что пришло в голову - высылка сигнала из потока. Может быть, кто-нибудь знает каким ещё способом можно организовать то, что требуется? P.S. На форуме нашёл только это - http://www.prog.org.ru/topic_23475_0.html (http://www.prog.org.ru/topic_23475_0.html). Там упомянули торрент-клиент из примеров Qt, но я так и не смог полностью понять, как а нём устроено обновление прогрессбара. Название: Re: Высылка сигнала из потока Отправлено: Странник от Февраль 21, 2013, 15:16 В exec() происходит отсылка сигналов. То получается что цикл крутится, а сигналы накапливаются в очереди. Как только цикл завершается, exec() отрабатывает и заваливает сигналами основной поток :) в exec() происходит обработка входящих сигналов и вызов слотов. исходщие сигналы на него не завязаны, насколько я помню. кроме того, у автора exec() вызывается до запуска цикла в работу, если он верно использует moveToThread.вообще - минимальный пример в студию, чтобы мы тут не фантазировали. Название: Re: Высылка сигнала из потока Отправлено: Igors от Февраль 21, 2013, 15:22 Что нужно сделать: из потока, который занимается какой-либо длительной операцией, нужно управлять прогрессбаром. Да, это и есть самое простое и правильное - если у Вас действительно while в другой (не главной) нитке :) Соответственно, первое, что пришло в голову - высылка сигнала из потока. Название: Re: Высылка сигнала из потока Отправлено: markie от Февраль 21, 2013, 15:54 Попробую выложить минимальный пример.
Client - главный поток. Создание треда: Код: void Client::createThread(LongAction *action) Вот ф-ция, в которой происходит скачка файла. Класс DownloadAction наследуется от LongAction (А LongAction от QObject). Код: void DownloadAction::readResponse() readResponse() - как уже наверно все поняли слот, который подвешен на сигнал readyRead(). _rowProgressBar - номер строки в QTableWidget (в нём на каждой строчке располагаются прогрессбары). P.S. сократил как мог, если что-то понадобится для наилучшего понимания, то пишите. Название: Re: Высылка сигнала из потока Отправлено: ViTech от Февраль 21, 2013, 16:29 Client::createThread и DownloadAction::readResponse где вызываются? Вы уверены, что код фактически выполняется в тех потоках, в которых Вы задумывали? Выше уже предлагали проверить с помощью QThread::currentThreadId.
Название: Re: Высылка сигнала из потока Отправлено: markie от Февраль 21, 2013, 18:53 Client - главный поток. currentThreadId() в слоте readResponse и в объекте Client разный.
Название: Re: Высылка сигнала из потока Отправлено: ViTech от Февраль 21, 2013, 19:28 По коду много еще всяких вопросов возникает, но, наверное, полезно будет по граблям походить. Так частенько, в конечном итоге, толка больше получается, чем если сразу все правильно делать :).
Цитировать _rowProgressBar - номер строки в QTableWidget (в нём на каждой строчке располагаются прогрессбары). А этот прогрессбар откуда данные для текущей позиции берет? Можно ли сразу в emit progress() передать текущую позицию? Тогда и action'у не надо знать, какой там прогрессбар к нему будет подключаться, и прогрессбару без разницы, кто ему текущую позицию сообщать будет. Можно еще выяснить, как часто будет вызываться emit progress(), и надо ли с такой частотой прогрессбар обновлять.И, если можно, такой оффтопный интимный вопрос: до знакомства с Qt, на каких языках писали, с какими фреймворками работали? :) Название: Re: Высылка сигнала из потока Отправлено: markie от Февраль 21, 2013, 21:44 >А этот прогрессбар откуда данные для текущей позиции берет?
Вызывается метод value и инкрементируется текущее значение. >Тогда и action'у не надо знать, какой там прогрессбар к нему будет подключаться, и прогрессбару без разницы, кто ему текущую позицию сообщать будет. Вообще, это всё делалось исходя из того, что на каждый экшен свой прогрессбар в таблице. >на каких языках писали, с какими фреймворками работали? C, C++ . Совсем чуть-чуть работал с mfc, вот сейчас кьют. Название: Re: Высылка сигнала из потока Отправлено: Old от Февраль 21, 2013, 22:07 2 markie: Скажите, а что пишется в консоль при выполнении вашей программы?
Смущает меня эта строка: Код
Если вы хотите, что бы нить завершалась, при завершении загрузки, то нужно так: Код
Название: Re: Высылка сигнала из потока Отправлено: markie от Февраль 22, 2013, 01:46 2Old: эти 2 записи эквивалентны, соответственно в консоль ошибок не выдаётся.
Название: Re: Высылка сигнала из потока Отправлено: carrygun от Февраль 22, 2013, 07:16 А где код чтото в духе:
Код То есть тред будет весеть в экзеке и все. Работа action'а быдет выполнена в том треде, где она будет вызвана, поэтому ее надо вызывать созданным тредом. По представленному коду не видно где вызвается это самая "работа", смею предположить что тред болтается сам по себе, а работа вызвается в главном потоке. Отсюда и такой эффект Название: Re: Высылка сигнала из потока Отправлено: Igors от Февраль 22, 2013, 12:21 Попробую выложить минимальный пример. Ну вот допустим кто-то хочет помочь, что он должен делать с таким "минимальным примером"? Создать тестовое приложение, хедеры для Ваших классов, откуда-то догадаться об их ф-ционале и многое др. Вы бы стали этим заниматься? Ну так почему думаете кто-то другой станет? Вот если бы исходники + pro файл, тогда желающие нашлись бы. Понятно что Вам проще вырезать что-то из исходников чем возиться с каким-то тестовым проектом - ну так вырезка-то ничего не дает.... P.S. сократил как мог, если что-то понадобится для наилучшего понимания, то пишите. В большинстве случаев автор находит ошибку сам в процессе подготовки тестового проекта |