потока. Я просто хочу сделать работу бд в отдельном потоке, чтобы приложение было отзывчивым. Вроде бы все просто.
Смотрел много исходников на гитхабе, видел примеры как в другом потоке делают запрос, потом все данные считывают в массив и по сигналу возвращают этот массив в гуи.
У меня есть сомнения в этом затратном способе.
Но есть и обратная сторона. Когда сделан запрос, sqlquery почти не занимает память. SqlQuery начинает занимает память по мере прохождения по элементам
while (query.next()) { ...}
. Т.е. по сути при итерации идет обращение к бд? Т.к. пытался делать тяжелые запросы и они выполняются моментально. Значит не красиво делать запрос из другого потока, потом возвращать по сингналу QSqlQuery и из гуи пытаться считывать данные.
Почему меня это беспокоит. При андроид программировании на яве, если гуи зависает, то случается anr (application not response, т.е. приложение не отвечает). Гугл рекомендует делать запросы в другом потоке (в room уже кидает исключение если обращение к бд из гуи идет).
Как правильно сделать запросы из другого потока? Можно кусок кода или словесное описание алгоритма пожалуйста
у меня в последнем проекте все общение с БД в фоне. возвращаю из фонового процесса данные через сигнал в QVariant-e. Затрат нет, поскольку QVariant хранит implicit shared массив.
небольшой недоработаный пример
Это во-первых, мало имеет смысла. Обычно запросы все быстрые, а если они НЕ быстрые, их надо сделать быстрыми. И обычно человек, работающий в GUI c данными, должен сначала получить данные, чтобы потом с ними сделать какое-то следующее дейтсвие. Поэтому вынос общения с БД в отдельный поток практически не имеет смысла. Однако, бывают сложные случаи, когда это делать всё же приходится. Про возможность -- там всё просто, всё так же , как в главном потоке, толькь надо не делать более одного запроса через одно соединение к БД в одно и то же время, и следить за ownership объектов Qt -- некоторые объекты могут "работать" только в том потоке, которому принадлежат, это всё описано в документации. Соотв. тебе надо будет сделать (почти наверняка) очередь запросов и очередь результатов, и сохранять данные (результаты) запросов в БД. Так имеет смысл делать только запросы на выборку, изменяющие данные запросы стоит делать СТРОГО СИНХРОННО, в основном потоке.
Когда сделан запрос, sqlquery почти не занимает память. SqlQuery начинает занимает память по мере прохождения по элементам while (query.next()) { ...} . Т.е. по сути при итерации идет обращение к бд? Т.к.Да, именно так. и при этом важно понимать, что когда ты сделал EXEC , но не выбрал данные , запрос ещё НЕ ВЫПОЛНЕН, данные надо все выбрать, сохранить куда-то, и затем освободить соединение для работы другого запроса.
Ну это называется реактивным программированием (или акторным программированием, не различаю их). То есть ты другому потоку посылаешь сообщение "выполни этот запрос". Другой поток, когда добирается до твоего сообщения, выполняет запрос, формирует ответ и посылает в твой поток сообщение с ответом. Соответственно, твой поток, когда добирается до этого сообщения, делает с ним что нужно. Это можно сделать например через сигналы/слоты - вызов сигнала эквивалентно посыланию сообщения
Обсуждают сегодня