LINUX.ORG.RU

QMetaObject::invokeMethod - поясните работу

 , , ,


1

1

Добрый день в документации Qt про QMetaObject::invokeMethod (http://doc.qt.io/qt-5/qmetaobject.html#invokeMethod) есть пункт:

If type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop.


Вопрос: что за QEvent будет послан и куда?

★★★★★

Если верить сорцам - QMetaCallEvent.

RazrFalcon ★★★★★
()

Что бы было понятней - вызываемый метод не будет вызван прямо сейчас и не будет блокировать выполнение текущего потока. Вместо этого, он будет обёрнут в наследника QEvent, который будет обработан в главном цикле обработки сообщений(который собственно и есть очередь) в потоке, в котором запущен qcoreapplication::exec.

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

в потоке, в котором запущен qcoreapplication::exec.

Не совсем так. Событие будет положено в очередь того потока, которому принадлежит объект, метод которого вызывается. И будет вызван в контексте этого потока.

BRE ★★
()

RazrFalcon, pon4ik, BRE, ребят, чтобы не начинать новую тему, растолкуйте пожалуйста еще пару моментов.
1. Сигналы (типа clicked) генерируются(emit) в обработчиках(handlers) событий?
2. Присоедененные слоты для сигналов также вызываются внутри соответсвующего обаботчика?

rumgot ★★★★★
() автор топика
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

1. Не распарсил. 2. Если сигнал и слот в пределах одного потока - то это тупо вызов функции. Никаких событий нет.

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

Сигналов типа clicked - нет. Есть события. Основной цикл Qt gui приложения очень приблизительно выглядит так:

  • Проверить ли есть ли события от подсистемы gui (x11 или win32 и.т.п всякие select и WaitMessage), если есть - обработать
  • Проверить есть ли события от сокетов и прочих дескрипторов которые обрабатываются асинхронно, , если есть - обработать
  • Проверить есть ли в очереди слоты которые нужно вызвать, если есть - вызвать
  • Уснуть пока не появится одно из событий выше или не истечёт ближайший таймер

Как это реализовано под конкретную ОС нужно смотреть в реализациях QApplication::exec.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 2)
Ответ на: комментарий от RazrFalcon

pon4ik. Постойте. Но вот тот же QPushButton. У него есть сигнал clicked (унаследованный). При клике мышью на данном объекте ему (этому объекту) отправляется событие QMouseEvent и далее в обработчике события этого объекта(mousePressEvent()) будет происходить emit сигнала clicked. Так вот мне и интересно, в какой момент будут вызываться присоединенные к данному сигналу слоты?

rumgot ★★★★★
() автор топика
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

Если сигнал и слот в одном потоке - то сразу. То есть как вызов обычной функции. Просто с сахаром/MOC.

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

Зависит от типа соединения. Если соединение direct - то слот будет вызван как обычный коллбэк. Если queued - то вызов слота будет поставлен в очередь цикла обработки событий. А вот в какой именно цикл, я не помню(не имел серьёзных дел с Qt уже 7+ лет :)), но по идее, в цикл потока в котором был создан обьект, если поток имеет свой цикл, и в основной цикл приложения в противном случае, возможно всегда в главный цикл. Если auto - выбирается direct, если обьекты имеют одинаковые потоки создания и queued в противном случае. Точнее в доке должно быть написано, а ещё точнее в сорцах.

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

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread

Вот как обтекаемо написано. Но если глянуть в сорцы QEventLoop и прочих processEvent, можно высмотреть, что указатель на цикл обработки событий хранится в tls, и если не задан - выбирается цикл qcoreapplication.

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

Но, стоит понимать, что если речь идёт о gui событиях, они всегда(без использования нативного api и прочих хаков), обрабатываются в потоке вызвавшем QApplication::exec. Собственно осуществление этого вызова и делает этот поток тем самым main/gui потоком.

Т.е. отвечая на твой вопрос - вызов(в смысле invoke) слота произойдёт после того, как событие попадёт в очередь главного цикла и обработаются предыдущие события, в контексте gui потока. А реальный вызов слота произойдёт в зависимости от типа соединения, потока в контексте которого был создан, или куда был перемещён объект(предоставляющий слот), наличия запущенного QEventLoop в потоке объекта(предоставляющий слот).

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от rumgot

Вот это:

При клике мышью на данном объекте ему (этому объекту) отправляется событие QMouseEvent

Не есть верно. Точнее, не совсем верно. При клике мышью, событие будет помещено в хвост очереди событий gui. Устройство этой очереди зависит от платформы, но интерфейс всегда похож(ибо придумать что-то умнее сложно) и представляет собой функцию дай_следующее_событие_или_усыпи_поток_пока_не_будет_следующего_события[_или_не_пройдёт_таймаут]. Вот когда событие будет вытащено из этой очереди, потоком который её разгребает, оно дальше будет диспетчеризовано в нужный коллбэк(обработчик события).

Что бы разобраться - крайне рекомендую тебе вручную реализовать следующие вещи в порядке перечисления:

  • Пул потоков выполняющих задачи, которые ставит отдельный поток
  • Gui приложение на основе нативного api(X11 или win32 или чего там под макось есть)
  • Многоклиентный tcp echo или chat сервер на основе

    select или epoll

  • Найти 10 концептуальных отличий
pon4ik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.