QThread + QtSql: Асинхронные запросы
Метки >:3, qt, sql, многопоточность
Всем добрых суток времени! Думаю, подавляющее большинство Qt разработчиков, трогавших работу с базами данных, знают, что QtSql создан однопоточным. Даже более того, соединения с базой данных нельзя передавать между потоками, нельзя передавать и курсоры, и запросы, и, вообще, всё. Почти столь же подавляющее большинство встречало вторую проблему - отсутствие стоянок "Free-Bike" в радиусе мили от поискового запроса, как же эти потоки добавить. Пора ударить коммунистической рукой по классовой несправедливости! УВАГА: Перед вами настоящий велосипед из настоящих костылей без применения синей изоленты! Используйте на свой страх и риск! tl;dr
Итак, как вынести соединение с базой в другой поток? Как и всё остальное, через QObject
Добавим поддержку запросов:
Почти всё. Осталась одна деталь, нужно вызвать функцию инициализации метатипов:
В принципе, всё, далее этот класс можно использовать следующим образом:
Ну вот и всё, асинхронные многопоточные запросы реализованы. При желании таких рабочих можно объединить в пулы, реализовать в них больше от QSqlResult, но это уже другая история. Не по теме: Обо всех замечаниях по тексту и коду - кричите, как резанные. Upd1: В статье был ряд опечаток и неточностей. В частности, класс в ряде мест назывался lpWorker, в одном из конструкторов ошибочно передавался this в QThread. Спасибо, Avazart, я верю в тебя, даже если ты не веришь в меня. |
Всего комментариев 11
Комментарии
-
Запись от Avazart размещена 14.01.2016 в 12:50
Обновил(-а) Avazart 14.01.2016 в 12:56 -
Исправил. Worker потому что во мне погиб сочинитель имён классов. В зародыше.
А есть альтернативы? Вот я за час в обнимку с гуглом не нашёл. Я бы и не выкладывал, если бы вы, к примеру, написали в бложике чего-нибудь на тему. Но, увы, вы делали интересный и, одновременно, избыточный инструмент, который запросто заменяется DependencyWalker'ом.Запись от icpu размещена 15.01.2016 в 06:32 -
Цитата:если бы вы, к примеру, написали в бложике чего-нибудь на тему.
Но для того что бы оценить ваш код этого не нужно.
Цитата:заменяется DependencyWalker'ом.
Цитата:Worker потому что во мне погиб сочинитель имён классов. В зародыше.
Worker обычно класс который передается в поток, а у вас непонятно что, даже не Controler
Цитата:А есть альтернативы?
За один только
можно ...C++ (Qt) 1
moveToThread(th);
А ведь есть еще:
C++ (Qt) 1 2 3 4 5
Worker::~Worker() { th->terminate(); db.close(); th->deleteLater(); }
Запись от Avazart размещена 15.01.2016 в 11:29
Обновил(-а) Avazart 15.01.2016 в 11:39 -
Цитата:DependencyWalker и иже с ними
Цитата:Worker обычно класс который передается в поток, а у вас непонятно что, даже не ControlerfAa
переименую, а методы в_0(...); _1(...);
. Моё право. А ваше право - плеваться и выть.
Цитата:можно ...moveToThread(th);
не угодил? Утечек не создаёт, контроль над объектом не утекает. Как же сделать иначе, унаследовать QThread? Тогда прошу ознакомиться с холиваром, а не на потоки кивать.
Ещё замечания?
UPD:Worker
по логике работы класса скорее Executor. Получает задание через стандартную очередь и выполняет его. Но был он назван Worker'ом, так теперь и есть.Запись от icpu размещена 15.01.2016 в 11:50
Обновил(-а) icpu 15.01.2016 в 11:57 -
Цитата:Моё право. А ваше право - плеваться и выть.
Цитата:Извините, что задел ваши религиозные чувства, но я агностик,
Цитата:Чем moveToThread(th); не угодил?
Цитата:Тогда прошу ознакомиться с холиваром, а не на потоки кивать.
Для использования годится как наследование(в зависимости от ситуации конечно), так и передача "рабочего" объекта в поток, но явно не то ... что у вас.
Кстати между прочем кроме QThread есть еще и модуль QConcurent.
Читайте последние сообщение в той теме:
Классы для работы с БД насколько я знаю именно такие.Запись от Avazart размещена 15.01.2016 в 13:59
Обновил(-а) Avazart 15.01.2016 в 14:29 -
Цитата:Это не религия, это культура
Цитата:Ну погуглите тема избитая. Я же говорю прежде чем постить стоило хотя бы чуть почитать про потоки.
Ознакомьтесь с примерами из официальной документацией
, в которой написано, что годитсяпередача "рабочего" объекта в поток
, как у меня и делается. Нэ?
модуль QConcurent
перемещает параметры-объекты в создаваемые им потоки (или передаваемый ему пул потоков), хотя классы БДмогут использоваться только в том потоке, в котором они созданы
. См.Worker::init()
Пожалуйста, проверьте работоспособность класса. Вдруг окажется. что это быдлокожий уродец работает, и не создаёт при этом лишних сущностей.Запись от icpu размещена 15.01.2016 в 17:03 -
Цитата:Выберите название для этого класса, будет оно. Без шуток.
Цитата:как у меня и делается. Нэ?
Вы в рабочем классе определяете объект класса потока, а затем передаете объект этого рабочего класса (а вслед за ним тянется и объект потока) в поток. Тут даже предположить какие могут быть последствия сего тяжело, да в принципе и не нужно ибо видно что быдлокод и будет быдлокодом даже если будет компилится, хотя бы из-за самой структуры кода.Запись от Avazart размещена 15.01.2016 в 17:28
Обновил(-а) Avazart 15.01.2016 в 18:32 -
Цитата:Пока претендует только на нецензурное название.
будет оно. Без шуток.
Цитата:объект класса потока, а затем передаете объект этого рабочего класса (а вслед за ним тянется и объект потока) в поток
Цитата:быдлокод и будет быдлокодомЗапись от icpu размещена 20.01.2016 в 07:23
Обновил(-а) icpu 20.01.2016 в 07:40 -
Цитата:Эммм, что? Где? Вы думаете, я просто так указатели на QThread использовал, для фана? UPD: Да, была опечатка. Исправил.Нифиговая опечатка.
C++ (Qt) 1
th = new QThread(this);
Цитата:Напишите лучше, ткните меня в грязь лицом.
Да и кому действительно надо смотрит в доку и читает книги как советуют.Запись от Avazart размещена 20.01.2016 в 12:37
Обновил(-а) Avazart 20.01.2016 в 12:38 -
Цитата:
Вы привязались к созданию потоков, я признал опечатку, исправил. /* Если бы я намеренно делал поток потомком объекта, я бы не хранил явно указатель на него, а фильтровал бы детей. Благо, поток нужен раз в сто лет в обед. */ Тем не менее, указанных вами последствий не наступает, потому как вначале создаётся поток, указатель на который передаётся в объект, а потом контекст объекта передаётся в контекст потока, т.е. поток остаётся в старом контексте. Потоки не блокируются, утечек не происходит, неопределённого поведения так же нет. Даже если не утилизировать созданый на куче поток, он и его данные не утекут с завершением приложения.
В чём конкретно вы видите ошибку? В том, что я не отнаследовался от класса потока? В том, что выложил черновую заготовку, которую ещё нужно дорабатывать? В том, что я явно вызываю invoke?Запись от icpu размещена 20.01.2016 в 12:50 -
Цитата:Не увидел указаний на ошибки, неточности или что-нибудь в этом духе.
Хотите более явных указаний? Пожалуйста - выкиньте свой код на помойку, и завязывайте с программированием.
Цитата:Вы привязались к созданию потоков, я признал опечатку, исправил
нефиг пихать все в одну кучу, и отводить одному классу кучу задач.
Есть класс "рабочий" который ответственен за всю работу и передается в класс поток, и есть класс "контролер"
который создает оба объекты этих классов управляет,связывает итп.
И все прозрачно, а не так как у вас.
Но я уже не напоминаю что можно было обойтись использованием QtConcurent что выглядело бы куда проще.
Цитата:Даже если не утилизировать созданый на куче поток, он и его данные не утекут с завершением приложения.Запись от Avazart размещена 20.01.2016 в 13:18
Обновил(-а) Avazart 20.01.2016 в 13:28