![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
flankerr |
![]() ![]()
Сообщение
#1
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 356 Регистрация: 9.1.2008 Пользователь №: 65 Спасибо сказали: 2 раз(а) Репутация: ![]() ![]() ![]() |
В главном потоке создаётся пользовательский поток. Из главного потока отсылается сигнал связанный со слотом класса потока пользователя. В контексте какого потока будет вызван слот ?
|
|
|
![]() |
SABROG |
![]()
Сообщение
#2
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
Я думаю, что в контексте пользовательского потока, если в нем вызывается exec() в run(). Сигнал поставится в очередь и поток его обработает, когда завершит выполнение блокирующих операций.
|
|
|
flankerr |
![]()
Сообщение
#3
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 356 Регистрация: 9.1.2008 Пользователь №: 65 Спасибо сказали: 2 раз(а) Репутация: ![]() ![]() ![]() |
вот и я так думал а сейчас проверил и сильно обламался
![]() если вызвать QThread::currentThreadId() в главном потке и в слоте класса дочернего потка то они совпадут а вот QThread::currentThreadId() вызванный в run будет другим. connect вызывался и до вызова start и после, и до выхова exec дочернего потка и после (в главном потоке) в coonnect передавался тип Qt::QueuedConnection и оставлял по умолчанию - рзультат один - слот вызывается в контексте потока сигнала точнее сказать слот будет вызван в контексте потока в котором был создан объект содержащий слот. Сообщение отредактировал flankerr - 11.6.2009, 12:53 |
|
|
SABROG |
![]()
Сообщение
#4
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
Кажись вспоминаю, либо connect должен делаться в run() либо объект к которому коннектишся должен создаваться в run.
|
|
|
flankerr |
![]()
Сообщение
#5
|
Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 356 Регистрация: 9.1.2008 Пользователь №: 65 Спасибо сказали: 2 раз(а) Репутация: ![]() ![]() ![]() |
опытным путём пришёл к тому что объект должен создоваться в run
|
|
|
igor_bogomolov |
![]()
Сообщение
#6
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 1215 Регистрация: 22.3.2009 Из: Саратов Пользователь №: 630 Спасибо сказали: 235 раз(а) Репутация: ![]() ![]() ![]() |
Цитата(flankerr) опытным путём пришёл к тому что объект должен создоваться в run Можно так же воспользоваться методом QObject::moveToThread-----upd----------------------------------------------------------------------------------------- Что то меня терзают смутные сомнения.
Может я уже что то подзабыл. Но мне кажется, что в таком случае слот readSocket будет вызван в главном(GUI) потоке. Для того чтобы слот вызвался в дочернем потоке, нужно в коннект добавить Qt::DirectConnection. Или в конструктор класса добавить moveToThread(this); Сообщение отредактировал igor_bogomolov - 11.6.2009, 13:39 |
|
|
SABROG |
![]()
Сообщение
#7
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
А объясните мне такую вещь. Если запустить timerEvent для объекта в главном потоке и в нем эмитить сигнал для дочернего потока, то слот этого потока выполняется в главном потоке (видимо причина в том, что сам объект QThread находится в главном потоке). Однако, если эмитить сигнал из run() для главного потока, то слот вызывается в главном потоке (что есть правильно).
Вопрос в том как отправить сигнал дочернему потоку из объекта главного потока, чтобы слот выполнялся в дочернем потоке? При этом moveToThread или создание того же QMainWindow внутри run() совершенно не выход. В первом случае вернутся из moveToThread не получится, а второй случай вообще бредовый. Сообщение отредактировал SABROG - 11.6.2009, 16:22 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#8
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
SABROG |
![]()
Сообщение
#9
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#10
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
SABROG |
![]()
Сообщение
#11
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
вроде вот эта Прикол в том, что я сам себе ответил. Однако проблема остается, если эмитить сигнал из главного потока в дочерний, то слот на этот сигнал выполнится в главном потоке. Это ведь не есть правильно, блокировать основной поток. Интересно как это можно обойти используя стандартные средства сигналов/слотов и цикла событий. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#12
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Я с потоками работал толькот одним способом:
Переопределяю в наследнике метод run(), из главного вызваю start(). Шлю в поток сигнал, управление сразу возвращается в главный поток. |
|
|
SABROG |
![]()
Сообщение
#13
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
Попытался воссоздать ситуацию:
Хотел сделать что-то общения между потоками посредством сигналов. Главный поток пытается раз в секунду послать сигнал в дочерний поток, но слот вызывается в том же главном потоке несмотря на насильную установку флага Qt::QueuedConnection. Т.е. как ни крути, а все слоты вызываются из гуишного потока. А я хотел, чтобы цикл событий дочернего потока принял эвент о сигнале в run() и выполнил слот в своем потоке. Сообщение отредактировал SABROG - 11.6.2009, 17:39 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#14
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
BRE |
![]()
Сообщение
#15
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Однако проблема остается, если эмитить сигнал из главного потока в дочерний, то слот на этот сигнал выполнится в главном потоке. Это ведь не есть правильно, блокировать основной поток. Интересно как это можно обойти используя стандартные средства сигналов/слотов и цикла событий. Исходные данные: в главном потоке создается дочерний поток. Тут нужно сразу понять, что объект (!) дочернего потока (QThread и его наследники) создается в главном потоке и находится в контексте главного потока. Контекст дочернего потока образуется только после запуска потока (QThread::start). Контекст дочернего потока состоит из метода run(), все объекты созданные в нем, будут располагаться в контексте дочернего потока. Теперь вспомним как Qt работает с межпоточными сигналами: при вызове сигнала, слот-обработчик которого находиться в другом контексте, Qt поместит специальное событие в очередь потока получателя и при очередном кванте времени из метода exec будет вызван нужный слот. Т.к. exec крутиться в контексте дочерней нити этот слот будет вызван в его контексте. Почему же происходит что слот нити выполняется в главном? Для Qt объект дочерний нити находиться в контексте главной нити, поэтому сигнал-слот связывается на прямую и соответствено вызывается в контексте главной нити. |
|
|
SABROG |
![]()
Сообщение
#16
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
Т.е. как ни крути, а все слоты вызываются из гуишного потока. как ты такой вывод сделал?Я решил поэкспериментировать и пришел к такому вот странному решению:
Я назвал этот метод методом "Мюнхаузена" ![]() Теперь действительно сигналы отправляются из главного потока и слот вызывается в дочернем потоке. |
|
|
BRE |
![]()
Сообщение
#17
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Я решил поэкспериментировать и пришел к такому вот странному решению:
Я назвал этот метод методом "Мюнхаузена" ![]() Теперь действительно сигналы отправляются из главного потока и слот вызывается в дочернем потоке. Этот метод был разработан несколькими днями ранее kuzulis. ![]() http://www.prog.org.ru/topic_9694_0.html |
|
|
Litkevich Yuriy |
![]()
Сообщение
#18
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
SABROG |
![]()
Сообщение
#19
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
Этот метод был разработан несколькими днями ранее kuzulis. Если верить его словам, то даже не им, он где-то это увидел ![]() Жаль авторство не могу себе присвоить ![]() Улыбнула фраза Константина Цитата собсна, вообще не удивительно. а вот tc->moveToThread(tc) улыбнуло...ассоциируется с картинкой, где чел сам себе в зад залазит /* может видел кто? */ Улыбающийся Ну хотябы могу себе название метода "Мюнхгаузена" присвоить ![]() --- Кстати, скорее всего человек увидел этот метод отсюда http://forum.vingrad.ru/forum/topic-241300...y1737536/0.html Этот топик один из первых выдается в гугле на поиск moveToThread. Еще немного погуглил и нашел такую переписку с канала #Qt: Цитата [04:58] <daniel> thiago_home: Yeah I just noticed I don't have to wait. [04:59] <daniel> Is "thread.start(); thread.moveToThread(&thread);" ok? [05:00] <thiago_home> yes Собственно, я так понимаю, что thiago_home это Thiago Macieira, раз он одобряет этот метод, то почему бы троллям не предложить ввести что-то типа флага, чтобы объект сразу сам в себя перемещался внутри метода start(). wasyota тоже такой метод предлагает. --- Может поместить это решение в "Секреты и интересные возможности" ? Сообщение отредактировал SABROG - 11.6.2009, 18:53 |
|
|
igor_bogomolov |
![]()
Сообщение
#20
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 1215 Регистрация: 22.3.2009 Из: Саратов Пользователь №: 630 Спасибо сказали: 235 раз(а) Репутация: ![]() ![]() ![]() |
Жаль авторство не могу себе присвоить , хотя конечно решение самом себе в голову напрашивается. Себе авторство тоже присвоить не могу, но если посмотришь здесь (в атаче), увидишь, что я пришел к такому же решению. Я тогда только разбирался в этом вопросе, и сделал так скорее по незнанию. Я предлогаю делать так На мой взгляд, это будет правильнее.
|
|
|
BRE |
![]()
Сообщение
#21
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
Я к самому классу QThread и его наследникам отношусь немного по другому.
Объект этого класса использую только для управления потоком, я не расширяю его функциональность. Т.е. есть методы управления и проверки состояния потока (с ними работа идет из запустившего потока) и как-бы отдельно метод run, который и описывает сам поток. Вот в нем я создаю необходимые объекты связываю их сигналами с объектами в других потоками и т.д. Управление идет через объект находящийся в контексте родительского (основного) потока, а что там в потоке делается это уже к run(). Блин, не знаю как получилось описать. ![]() С точки зрения архитектуры подхожу к объектам потоков по другому... ![]() |
|
|
SABROG |
![]()
Сообщение
#22
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#23
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
BRE |
![]()
Сообщение
#24
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1112 Регистрация: 6.3.2009 Из: Ростов-на-Дону Пользователь №: 591 Спасибо сказали: 264 раз(а) Репутация: ![]() ![]() ![]() |
С точки зрения архитектуры подхожу к объектам потоков по другому... Получается, чтобы связать слот в потоке и сигнал из главного окна тебе приходится создавать дополнительный объект в run() к которому все и привязывать? Да, я не добавляю слоты в класс наследник от QThread (не расширяю его функциональность). А как ты и написал делаю отдельный класс, который содержит сигналы/слоты и он выполняет всю работу, его создаю в run и настраиваю связи. |
|
|
SABROG |
![]()
Сообщение
#25
|
![]() Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#26
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Собственно почему странно, если так можно самого "потока" запнуть в самого себя, то почему он сам этого не делает.
Т.е. должно было бы быть так: и все функции, объявленные в нём, уже в другом потоке.
|
|
|
![]() ![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 22.6.2025, 17:03 |