LINUX.ORG.RU

Из какого потока вызовется слот в Qt (5).

 , ,


0

2

Помогите разобраться, пожалуйста. Сначала в одном потоке к слоту объекта привязывается сигнал чередующим соединением (Qt::QueuedConnection). За тем, объект перемещается в другой поток (moveToThread()). Внимание, вопрос: при отправке сигнала, в каком потоке будет выполнен слот, или иными словами в очередь событий какого потока ляжет сигнал, первого, где было соединение, или второго, где поселился объект?

★★★

слот может быть вызван в том потоке, куда ты сделал moveToThread. Но там тоже надо постараться.

после moveToThread() поток будет пересобачен в другой поток. там будет вызван сигнал ТОЛЬКО если там работает QEventLoop. Если быть точным то нужен только QAbstractEventDispatcher(реализация отдается самим Qt) но она как-то странно завершается(крешит код).

i36_zubov
()

то есть. у потока есть список объектов(это не так но неважно, я для упрощения пишу).

когда ты отправляешь сигнал, то ты вызываешь функцию из moc-файла. она видит что сигнал идет не напрямую(ибо ты сделал moveToThread и адрес треда не совпадает) и пакует аргументы. при этом она создает массив указателей на аргументы. он-то и уходит в поток-получатель с адресом объекта и индексом слота.

Далее линукс как-то передаст эти данные в другой поток. Там они возьмутся из очереди и подадутся на вход функции из moc-файла объекта-получателя. там нарисован switch от индекса и вызывается уже слот. С дереференсингом аргументов по указателям.

Потом данные херятся.

i36_zubov
()
Ответ на: комментарий от i36_zubov

Извини, я ничего не понял.

слот может быть вызван в том потоке, куда ты сделал moveToThread

«может», или «должен»?

normann ★★★
() автор топика
Ответ на: комментарий от normann

объект живет в потоке куда его сунули. по умолчанию - где создан.

но в том же потоке должен быть QEventDispatcher.нужен QEventLoop, дефолтный QThread::run -он создает луп, или руками дрыгать QAbstractEventDispatcher

i36_zubov
()
Ответ на: комментарий от normann

Он говорит на уровне на котором я себе это представлял впервые увидев кути и сложные мультипоточные фреймворки в частности (и не зная плюсов конечно), поэтому я бы подождал кого-нибудь кто разбирается получше на твоём месте — без «странно завершается», «как-то» и «данные херятся».

anonymous
()
Ответ на: комментарий от i36_zubov

Qt4 протух уже. В Qt5 QEventLoop создается автоматически при старте QThread.

anonymous
()

Слот будет вызван в контексте треда переданного в аргументе moveToThread.

anonymous
()
Ответ на: комментарий от anonymous

слот может быть вызван в том потоке, куда ты сделал moveToThread

На сколько я могу быть в этом уверен? Это из личного наблюдения или есть какое-то правило?

Я спрашиваю потому что, например, если я только проверяю это эмпирическим путём, то не могу быть уверен что увиденное поведение является правилом.

normann ★★★
() автор топика
Ответ на: комментарий от normann

QueuedConnection - это вызов через очередь. Постановка в очередь проходит в момент вызова сигнала. Если к этому момент moveToThread уже отработал слот будет вызван в соответствующем треде.

anonymous
()
Ответ на: комментарий от anonymous

Очередь есть и не только в потоке где поселился объект, она так же есть и в потоке где был вызван connect().

normann ★★★
() автор топика
Ответ на: комментарий от normann

В документации по QObject::moveToThread не зря написано:

this function can only «push» an object from the current thread to another thread, it cannot «pull» an object from any arbitrary thread to the current thread

То-есть когда объект жил в текущем потоке до вызова moveToThread, и кто-то приклеился к его слоту в режиме QueuedConnection, то вызов такого сигнала был либо уже обработан в текущем потоке, либо при вызове moveToThread его вызов будет перенесён в очередь другого потока, и это безопастно.

Другими словами, нет никаких «может быть». Сигнал ДО moveToThread будет вызван только в текущем потоке, а ПОСЛЕ только в перемещённом потоке.

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

Не знаю как вы связываете упомянутую цитату с тем что рассказываете (может цитата не та), но сказанное, эмпирическим путём на 5.11 под Linux у меня подтверждается.

normann ★★★
() автор топика
Ответ на: комментарий от normann

А вообще, я многое прошляпил из документации на QObject::moveToThread().

normann ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.