Название: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 06, 2011, 14:13 В слоте нужно узнать адрес объекта, который испустил сигнал. Можно конечно в параметрах сигнала передавать адрес. А можно ещё как-нибудь? Вроде в Qt для этого есть какие-то методы?
Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 14:25 sender() - прям и не догадаешься...
Название: Re: Как узнать кто излучил сигнал? Отправлено: Disaron от Февраль 06, 2011, 14:25 QObject::sender()
Название: Re: Как узнать кто излучил сигнал? Отправлено: Denjs от Февраль 06, 2011, 16:27 QObject::sender() старая песня о главном))) в общем случае - вы и не должны знать. никак и никогда.про QObject::sender()- как помню, ассистант рассказывает следующее: данный метод противоречит философии сигнал-слотов и работает только внутри одного потока. Если сигнал из другого потока - то метод возвращает "ничего" (оно и понятно - к моменту получения сигнала объект-источник давно уже мог быть уничтожен) Более того - понимаю так, что из этого следует и то, что работать оно не будет и в одном потоке если метод вызова слота - "квотед коннекшн". Возможно и при некоторых других типах соединений - тоже (в 4.5 ввели новые типы соединений - потому и не знаю). В общем, имхо, ссылка на объект-источник типа QPointer передаваемая с сигналом - это получше будет и поуниверсальнее, хотя и "более тяжелая конструкция". но QPointer::isNull() удобен. Название: Re: Как узнать кто излучил сигнал? Отправлено: Disaron от Февраль 06, 2011, 17:47 QObject::sender() старая песня о главном))) в общем случае - вы и не должны знать. никак и никогда.про QObject::sender()- как помню, ассистант рассказывает следующее: данный метод противоречит философии сигнал-слотов и работает только внутри одного потока. Если сигнал из другого потока - то метод возвращает "ничего" (оно и понятно - к моменту получения сигнала объект-источник давно уже мог быть уничтожен) Более того - понимаю так, что из этого следует и то, что работать оно не будет и в одном потоке если метод вызова слота - "квотед коннекшн". Возможно и при некоторых других типах соединений - тоже (в 4.5 ввели новые типы соединений - потому и не знаю). В общем, имхо, ссылка на объект-источник типа QPointer передаваемая с сигналом - это получше будет и поуниверсальнее, хотя и "более тяжелая конструкция". но QPointer::isNull() удобен. Название: Re: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 06, 2011, 18:29 QObject::sender() старая песня о главном))) в общем случае - вы и не должны знать. никак и никогда.про QObject::sender()- как помню, ассистант рассказывает следующее: данный метод противоречит философии сигнал-слотов и работает только внутри одного потока. .... В общем, имхо, ссылка на объект-источник типа QPointer передаваемая с сигналом - это получше будет и поуниверсальнее, хотя и "более тяжелая конструкция". но QPointer::isNull() удобен. Название: Re: Как узнать кто излучил сигнал? Отправлено: serg_hd от Февраль 06, 2011, 19:47 Если сигнал из другого потока - то метод возвращает "ничего" (оно и понятно - к моменту получения сигнала объект-источник давно уже мог быть уничтожен) неверно, при типе DirectConnection всё ок ;)Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 19:56 Если сигнал из другого потока - то метод возвращает "ничего" (оно и понятно - к моменту получения сигнала объект-источник давно уже мог быть уничтожен) неверно, при типе DirectConnection всё ок ;)Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 06, 2011, 20:02 Из другого птока можно только QueuedConnection... всё остальное черевато большими проблеммами... QBlockedQueuedConnection гарантирует что отправитель жив (он ждет ответа). Ну конечно если устроит по скоростиНазвание: Re: Как узнать кто излучил сигнал? Отправлено: serg_hd от Февраль 06, 2011, 20:18 Из другого птока можно только QueuedConnection... всё остальное черевато большими проблеммами... не чревато, у меня рабочий проект, веб-серфер работает как раз по такому принципу: второстепенные потоки шлют сигналы на главный гуишный поток (с целью создания qwebview), тип сигнала directconnection. Потоков доходило одновременно до 400, проблем никаких никогда не возникало.Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 20:51 не чревато, у меня рабочий проект, веб-серфер работает как раз по такому принципу: второстепенные потоки шлют сигналы на главный гуишный поток (с целью создания qwebview), тип сигнала directconnection. Потоков доходило одновременно до 400, проблем никаких никогда не возникало. у меня тоже на linux'e нормально работало, но при переносе на винду всё полетело. По сигналу из дочернего потока нужно было сделать ресайз окна... так вот это и падало. Да и прогрес бар не обновлялся.Дело в том, что при директ коннекшине код ГУИ потока будет исполняться в дочернем потоке, что само по себе опасно. Некоторые системы, например, иксы это могут переваривать, а некоторые - нет. (мог ошибиться в своих выводах) То что у вас не возникало проблем - ИМХО чистая удача... ЗЫ: сейчас попробую набросать пример. Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 21:23 А вот и пример(в аттаче)
Оказывается наврал... на линуксе тоже падает, зато хорошо показыват что так делать нельзя. Название: Re: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 06, 2011, 21:24 Дело в том, что при директ коннекшине код ГУИ потока будет исполняться в дочернем потоке, что само по себе опасно. Почитал асистент ещё раз про директКонекшн. Цитировать The slot is invoked immediately, when the signal is emitted. Ни слово про то, что слот будет выполнятся в потоке излучателя сигнала.Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 21:33 juvf, не там читали:
Цитата: Threads and QObjects Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread. Название: Re: Как узнать кто излучил сигнал? Отправлено: Disaron от Февраль 06, 2011, 21:58 А вот и пример(в аттаче) Видимо зависит от линукса и от версии кьют. У меня не падает, но при директе гадит:Оказывается наврал... на линуксе тоже падает, зато хорошо показыват что так делать нельзя. Код: QObject::setParent: Cannot set parent, new parent is in a different thread Название: Re: Как узнать кто излучил сигнал? Отправлено: serg_hd от Февраль 06, 2011, 22:20 не чревато, у меня рабочий проект, веб-серфер работает как раз по такому принципу: второстепенные потоки шлют сигналы на главный гуишный поток (с целью создания qwebview), тип сигнала directconnection. Потоков доходило одновременно до 400, проблем никаких никогда не возникало. у меня тоже на linux'e нормально работало, но при переносе на винду всё полетело. По сигналу из дочернего потока нужно было сделать ресайз окна... так вот это и падало. Да и прогрес бар не обновлялся.Дело в том, что при директ коннекшине код ГУИ потока будет исполняться в дочернем потоке, что само по себе опасно. Некоторые системы, например, иксы это могут переваривать, а некоторые - нет. (мог ошибиться в своих выводах) То что у вас не возникало проблем - ИМХО чистая удача... ЗЫ: сейчас попробую набросать пример. Название: Re: Как узнать кто излучил сигнал? Отправлено: Fat-Zer от Февраль 06, 2011, 22:27 А вот и пример(в аттаче) Видимо зависит от линукса и от версии кьют. У меня не падает, но при директе гадит:Оказывается наврал... на линуксе тоже падает, зато хорошо показыват что так делать нельзя. Код: QObject::setParent: Cannot set parent, new parent is in a different thread Вот что странно... если сначала запустить с QueuedConnection, а потом с директ, то всё работает (и плюётся сообщениями даже если не указывать предка в конструкторе), а если сразу с директ то рушится... почему - не понятно(почему работает... идеи?)... Сорри, спутал, у меня directconnection был когда проект писался на Qt Jambi. В сишном варианте сейчас посмотрел - QueuedConnection, работает одинаково в винде и линуксе. бывает... ;)Название: Re: Как узнать кто излучил сигнал? Отправлено: maxxant от Февраль 06, 2011, 23:40 В общем, имхо, ссылка на объект-источник типа QPointer передаваемая с сигналом - это получше будет и поуниверсальнее, хотя и "более тяжелая конструкция". но QPointer::isNull() удобен. для межпоточных взаимодействий QPointer кривой by disign. isNull() не атомарен и не гарантирует ничего на следующем же такте процессора. Его можно использовать только в одном потоке. Подробнее об этом написано в доках. Для межпоточных вещей есть пара из указателей QSharedPointer и QWeakPointer - если конечно хотите обойтись без мютексов и т.п. Название: Re: Как узнать кто излучил сигнал? Отправлено: Denjs от Февраль 07, 2011, 00:00 для межпоточных взаимодействий QPointer кривой by disign. isNull() не атомарен и не гарантирует ничего на следующем же такте процессора. Его можно использовать только в одном потоке. Подробнее об этом написано в доках. о как! секнкс) не дочитал, ассистант громаден как БСЭ)Для межпоточных вещей есть пара из указателей QSharedPointer и QWeakPointer - если конечно хотите обойтись без мютексов и т.п. Название: Re: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 07, 2011, 06:30 Цитировать Для межпоточных вещей есть пара из указателей QSharedPointer и QWeakPointer - если конечно хотите обойтись без мютексов и т.п. Что-то всё как-то сложно..... QPointer...... который не работает....... потом пара из указателей QSharedPointer и QWeakPointer.......я сделал просто, в лоб Код: emit(mySignal(QString, this); ps Код: QObject::setParent: Cannot set parent, new parent is in a different thread Название: Re: Как узнать кто излучил сигнал? Отправлено: maxxant от Февраль 07, 2011, 12:48 Что-то всё как-то сложно..... QPointer...... который не работает....... потом пара из указателей QSharedPointer и QWeakPointer....... QPointer работает, но для одного потока, т.е. isNull() не гарантирует что объект не будет удалён в другом потоке. В более ранних версиях Qt была аналогичная функция у QMutex, сейчас она закомменчена в коде, поскольку не имеет смысла, файл qmutex.cpp: Код: \fn bool QMutex::locked() Вам нужна блокировка самого объекта, QSharedPointer как раз и позволяет это. В примерах достаточно хорошо всё описано, достаточно один раз разобраться. Единственное, до Qt 4.6 не хватало пары функций для удобного их использования (помоему какого-то конструктора и operator=) - а начиная с 4.6 всё хорошо. я сделал просто, в лоб Код: emit(mySignal(QString, this); Будет работать, конечно, если вы уверены что указатель на объект будет валиден все время пока принимаются сигналы. Другое дело, что решение такое несколько хрупкое - через какое-то время можно забыть тонкости реализации, и тогда бац, будем валиться - хорошо если постоянно, плохо если эпизодически в самый неподходящий момент. ps Код: QObject::setParent: Cannot set parent, new parent is in a different thread объекту создаваемому во 2-м потоке укажите парента = 0. Qt не может удалять дочерний объект живущий в другом потоке и ставит parent=0 за вас - о чем и предупреждение. Удаляйте его сами при завершении потока, но не забывайте - указатель на этот объект, возможно, кому-то нужен - ведь я так понял, его вы передаёте вместе с сигналом в main thread. если что, вот примерная реализация для shared-weak pointers Код:
пояснения к примеру: -указатель на объект не должен храниться где-то ещё, кроме shared-weak указателей - иначе сам объект можно будет удалить через delete ... и никто об этом не узнает. -SharedPointer - содержит атомарный счётчик объектов, при достижении счётчиком нуля объект будет удалён автоматически. -QWeakPointer - слабая ссылка, по сути это указатель на SharedPointer с атомарными операциями. Сам по себе никогда не задерживает удаление объекта и нужен лишь для получения строгого указателя. -можно обойтись без QWeakPointer если логика несложна и нет риска хитрым алгоритмом задержать объекты в памяти (вызвать тем самым утечку) -ну и да, независимо от реализации никто не гарантирует корректность межпоточных операций для данных того объекта, к которому вы обращаетесь из разных потоков (то есть гарантируется только валидность указателя). Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 07, 2011, 14:05 Код: // создаём слабую ссылку на объект Код При этом деструктор ClientData может и не удалять какие-то члены - их удаление возьмет на себя отправитель Название: Re: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 07, 2011, 14:27 Тут понятно, а тут нет....
Ну во первых про то что излучателя может уже не быть не подумал. Но сейчас подумал и в принцепе таких мест нет. излучатель всегда будет жыть. Хотя теоретически в будущем может и не быть. Буду делать защиту. 2maxxant Во вторых, не понял я вашего примера..... Вот как я сделал Код: void MyClass::run() // второй поток теперь ваш пример. Требуется в слоте узнать излучателя сигнала. На сколько я понял ваш пример, то с сигналом передается указатель на какой-то объект, созданные во втором потоке, а не указатель на излучателя. может имелось ввиду так ран делать? Код: void MyClass::run() // второй поток Название: Re: Как узнать кто излучил сигнал? Отправлено: maxxant от Февраль 07, 2011, 16:41 Ну во первых про то что излучателя может уже не быть не подумал. Но сейчас подумал и в принцепе таких мест нет. излучатель всегда будет жыть. Хотя теоретически в будущем может и не быть. Буду делать защиту. Код: void MyClass::run() // второй поток ну может и не заморачиваться действительно - а там в будущем, возможно, найдётся решение получше. Заговорили про QPointer и т.д., я показал примерчик, но про this уже и забыл. Если this засунуть в QSharedPointer, то при удалении последнего указателя уничтожиться и сам объект, что весьма вероятно произойдёт в run(), так лучше не делать конечно )) Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 07, 2011, 17:02 Ну и вообще если планируется QueuedConnection, то лучше run не трогать (не перекрывать). Непрактично - по умолчанию run вызывает exec и нитка может принимать сигналы. А перекрыли - придется проверять eventLoop самому
Название: Re: Как узнать кто излучил сигнал? Отправлено: SimpleSunny от Февраль 07, 2011, 21:20 Никто же не запрещает в перекрытом run самому вызвать exec.
Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 07, 2011, 21:52 Никто же не запрещает в перекрытом run самому вызвать exec. Конечно - но ведь он управление не отдаст. Не смертельно - но неудобно/непрактичноНазвание: Re: Как узнать кто излучил сигнал? Отправлено: BRE от Февраль 07, 2011, 22:04 Конечно - но ведь он управление не отдаст. Не смертельно - но неудобно/непрактично Код
Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 07, 2011, 22:16 Конечно - но ведь он управление не отдаст. Не смертельно - но неудобно/непрактично Код
Название: Re: Как узнать кто излучил сигнал? Отправлено: BRE от Февраль 07, 2011, 22:21 Не возражаю, ночто оте точки до и после того - не придется ли там вставлять (утомительный) код? :) Ведь что-то могло случиться в processEvents. Необязательно, но проще работать "сигналами" с обеих сторон Ээээ. Не очень понял о чем речь.Что за "утомительный код", что может случиться в processEvents, и что мешает работать сигналами с двух сторон? Название: Re: Как узнать кто излучил сигнал? Отправлено: Igors от Февраль 07, 2011, 22:28 Ээээ. Не очень понял о чем речь. Ничто не мешает. Но если вся обработка в processEvents (при получении сигналов/событий) зачем тогда попусту перекрывать что делает run сам? Конечно имеет смысл если есть резоны для спец-обработки (остановить цикл или войти в специальный) - но они должны быть (редко).Что за "утомительный код", что может случиться в processEvents, и что мешает работать сигналами с двух сторон? Название: Re: Как узнать кто излучил сигнал? Отправлено: BRE от Февраль 07, 2011, 22:56 Igors, ты описал проблему:
Конечно - но ведь он управление не отдаст. Не смертельно - но неудобно/непрактично Я написал как это можно обойти. :) Конечно имеет смысл если есть резоны для спец-обработки (остановить цикл или войти в специальный) - но они должны быть (редко). "Редко-часто" это относительные понятия и очень субъективные. ;)Название: Re: Как узнать кто излучил сигнал? Отправлено: juvf от Февраль 14, 2011, 06:25 Что значит "перекрыть run"?
|