Название: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 21, 2011, 14:15 Есть основной поток, в котором создаются дочерние, при создании нового дочернего потока, необходимо передать в уже работающие некоторое значение, через сигнал/слот почему то не работает:
Код: class CMain Как правильно оповестить дочерние потоки об изменении какого либо параметра? При том что они в цикле что то считают с перерывами на сон. Название: Re: Передать значение из главного потока в дочерний Отправлено: Странник от Октябрь 21, 2011, 15:17 дочерние потоки крутятся у вас в doWork(), а цикл обработки событий тем временем не запущен. по-моему, лучше будет создать в потоке таймер, по сигналу которого будет вызываться слот doWork().
Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 21, 2011, 21:01 doWork() это просто отдельная функция объекта, который работает в дочернем потоке.
Вообще тут смысл не в таймере, а в том, что есть условно бесконечный цикл в объекте дочернего потока, и необходимо управлять определенными данными внутри этого бесконечного цикла, причем управление должно осуществляться из главного потока. Т.е. вопрос можно переформулировать так: как "заморозить" выполнение дочернего потока, изменить в нем данные, и запустить его на продолжение с новыми данными, при условии, что в дочернем потоке есть бесконечный цикл? Название: Re: Передать значение из главного потока в дочерний Отправлено: Igors от Октябрь 21, 2011, 21:27 дочерние потоки крутятся у вас в doWork(), а цикл обработки событий тем временем не запущен. Логичное соображение, но дело довольно темное, каким-то образом Qt умеет хранить события до тех пор пока не запустится eventLoop. Т.е. вопрос можно переформулировать так: как "заморозить" выполнение дочернего потока, изменить в нем данные, и запустить его на продолжение с новыми данными, при условии, что в дочернем потоке есть бесконечный цикл? Непонятно какой цикл имеется ввиду - свой или exec() (который Вы тоже запускаете). Если свой, то все то что уже многократно обсуждалось для "как остановить": нитка проверяет флажок, если он взведен, то забирает новые данные и работает с ними. Понятно что проверку надо вставлять в код нитки (и возможно во многие места), а также что "сразу" нитка перестроиться не сможет. Но никаких волшебных/легких путей здесь нет.Название: Re: Передать значение из главного потока в дочерний Отправлено: Странник от Октябрь 21, 2011, 23:28 doWork() это просто отдельная функция объекта, который работает в дочернем потоке. собственно я вам и предлагаю в качестве условно-бесконечного цикла использовать цикл обработки событий потока. для этого функцию doWork необходимо сделать слотом. это позволит выполнять doWork в потоке, не прерывая его работу при возврате из этого слота, а также запускать его в потоке уже после запуска цикла обработки событий. таким образом ваш поток сможет обрабатывать накопившиеся в очереди события (например, вызов слота on_setValue) после завершения doWork(), либо в процессе ее выполнения с помощью вызова processEvents(). Вообще тут смысл не в таймере, а в том, что есть условно бесконечный цикл в объекте дочернего потока, и необходимо управлять определенными данными внутри этого бесконечного цикла, причем управление должно осуществляться из главного потока. Т.е. вопрос можно переформулировать так: как "заморозить" выполнение дочернего потока, изменить в нем данные, и запустить его на продолжение с новыми данными, при условии, что в дочернем потоке есть бесконечный цикл? Код: class CMain Логичное соображение, но дело довольно темное, каким-то образом Qt умеет хранить события до тех пор пока не запустится eventLoop. хранить-то хранит, но не обрабатывает. разве что попробовать processEvents вызвать.Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 09:28 Непонятно какой цикл имеется ввиду - свой или exec() (который Вы тоже запускаете). Если свой, то все то что уже многократно обсуждалось для "как остановить": нитка проверяет флажок, если он взведен, то забирает новые данные и работает с ними. Понятно что проверку надо вставлять в код нитки (и возможно во многие места), а также что "сразу" нитка перестроиться не сможет. Но никаких волшебных/легких путей здесь нет.
[/quote]Цикл имеется ввиду свой while(true) который запускается внутри exec(). Что бы остановить его надо ввести какое то значение, а оно не вводится, т.к. цикл бесконечный и не отвечает на внешние запросы, т.е. до его окончания объект не может реагировать на сигналы извне. prcessEvent внутри цикла был бы выходом, но он только для QCoreApplication, а как его реализовать для отдельного самописного класса хз. Название: Re: Передать значение из главного потока в дочерний Отправлено: BRE от Октябрь 22, 2011, 09:33 А если цикла while(true) заменить на:
Код или Код
;) P.S. Кстати и цикла обработки событий внутри своих циклов легко крутить, если воспользоваться классом QEventLoop. Название: Re: Передать значение из главного потока в дочерний Отправлено: Странник от Октябрь 22, 2011, 10:56 prcessEvent внутри цикла был бы выходом, но он только для QCoreApplication, а как его реализовать для отдельного самописного класса хз. вызов QCoreApplication::processEvents() производит обработку очереди событий для вызывающего потока, что вас не устраивает?Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 11:31 А если цикла while(true) заменить на: Вот грубо говоря мне эту bool stopped и надо изменять, но оно не изменяется, т.к. не доходит сигнал, что надо ее изменить, т.к. крутится бесконечный цикл и обработка сообщений не происходит.Код
Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 11:33 prcessEvent внутри цикла был бы выходом, но он только для QCoreApplication, а как его реализовать для отдельного самописного класса хз. вызов QCoreApplication::processEvents() производит обработку очереди событий для вызывающего потока, что вас не устраивает?Код: while(true) Название: Re: Передать значение из главного потока в дочерний Отправлено: Igors от Октябрь 22, 2011, 12:02 Вот грубо говоря мне эту bool stopped и надо изменять, но оно не изменяется, т.к. не доходит сигнал, что надо ее изменить, т.к. крутится бесконечный цикл и обработка сообщений не происходит. Главная нитка изменяет stopped, а дочерняя это может отловить - в любой цикл можно вставить if (stopped) Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 15:32 Вот грубо говоря мне эту bool stopped и надо изменять, но оно не изменяется, т.к. не доходит сигнал, что надо ее изменить, т.к. крутится бесконечный цикл и обработка сообщений не происходит. Главная нитка изменяет stopped, а дочерняя это может отловить - в любой цикл можно вставить if (stopped) Как заставить отработать цикл обработки сообщений? Название: Re: Передать значение из главного потока в дочерний Отправлено: Igors от Октябрь 22, 2011, 16:01 Если посмотреть код из первого поста, то я так и делаю, но через сигнал/слот это не проходит,т.е. цикл обработки сообщений зависает до окончания работы while(true). То чего нет зависнуть не может, eventLoop создается в exec(). Если я правильно понял Вы хотите все делать на сигналах, без самопальных флажков. Тогда в дочерней нитке просто войдите в exec (не перекрывайте run). Нитка будет ждать сигнала/события. Пошлите его из главной, нитка начнет свое doWork, в котором уже можно звать processEvents и принимать следующие сигналы.Как заставить отработать цикл обработки сообщений? Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 18:42 Исходя из Ваших слов у меня вырисовывается картина кода, точно такая же как я привел в 1-м посте.
Но она, увы, не работает Если не сложно, покажите псевдокодом. Название: Re: Передать значение из главного потока в дочерний Отправлено: Странник от Октябрь 22, 2011, 19:25 Исходя из Ваших слов у меня вырисовывается картина кода, точно такая же как я привел в 1-м посте. такой вариант я приводил несколькими постами выше:Но она, увы, не работает Если не сложно, покажите псевдокодом. Код: class CMain Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 22, 2011, 21:00 такой вариант я приводил несколькими постами выше: Попробую 2-й вариант.1-й в моем случае не подойдет, ибо слишком много уже готового и отлаженного кода надо будет переделывать.Название: Re: Передать значение из главного потока в дочерний Отправлено: Igors от Октябрь 23, 2011, 09:02 Код Принципиально это ничем не отличается от того что привел Странник. Имеется ввиду что doWork будет делаться в слоте и что run просто запустит exec (как по умолчанию). Т.к. цикл событий запущен, дочерняя нитка сможет ловить сигналы в doWork Код
Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 23, 2011, 21:22 А что, если вызывать QCoreApplication::processEvent() непосредственно после испускания сигнала, а не в цикле каждый раз? Т.е.:
Код отработает,или все же есть какая то очередь (последовательность) действий, что может не успеть? Название: Re: Передать значение из главного потока в дочерний Отправлено: BRE от Октябрь 23, 2011, 21:28 Не поможет. Событие о сигнале кладется в очередь сообщений нити приемника и что бы это событие сработало - нужно крутануть цикл обработки событий именно этой нити.
Название: Re: Передать значение из главного потока в дочерний Отправлено: RedDog от Октябрь 24, 2011, 21:09 Попробовал вариант с processEvents(). Работает. Тему вроде как можно пометить решенной.
Хотя имхо это некоторый индусизм, т.е. не очень красиво. Буду думать над 1-м вариантом. |