Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Разработка баз данных _ Правильное закрытие QSqlQuery

Автор: 512es 2.12.2010, 13:30

bool stop = false;
int function()
{
    if (stop) return 1;
    QSqlQuery q;
    q.prepare("SELECT * FROM table WHERE id = ?;");
    q.addBindValue(5);
    if (!q.exec()) return 2; // ну, тут понятно.. ничего не остаётся больше кроме как писать ошибку и выходить из функции. q поидее удалится и ничего лишнего в памяти не останется
    while (q.next()) { // что будет если по каким либо причинам соединение с базой будет разорвано в момент получения строки?
        if (stop) {
            // надо ли делать тут q.clear() ???
            // поидее мы не все ещё выбрали строки запроса
            // или же, выйдя из function(), q удалится и закроет запрос сам?
            return 3;
        }
    }
    return 0;
}

void runFunction()
{
    function();
}


Переменная stop служит для прерывания выполнения цикла, например при закрытии программы.
Остаётся ли какой нибудь мусор в памяти при выходе из функции? Ведь соединение с базой остаётся открытым.

Иногда основной поток программы зависает.. Не пойму, в чём дело

Автор: panter_dsd 2.12.2010, 13:35

Не надо, QSqlQuery будет разрушен при выходе из зоны видимости.

Автор: Алексей1153 2.12.2010, 13:54

Цитата(512es @ 2.12.2010, 15:30) *
зависает..

а что именно происходит - просто ступор или окошко какое выпрыгивает ?

Автор: xls 2.12.2010, 15:06

Цитата
while (q.next()) { // что будет если по каким либо причинам соединение с базой будет разорвано в момент получения строки?

А вот это интересный вопрос.
Если разрыв соединения будет корректный, т.е. сервер СУБД остановлен, то все будет хорошо - данных не будет вообще.
Если же сервер стоит на другом узле и вы выдерните кабель сетевого соединения, то получите зависание запроса длительностью в тайм-аут соединения с сервером СУБД. И если запрос происходит в основном потоке процесса, то и общее зависание.

Автор: 512es 2.12.2010, 15:41

Цитата(Алексей1153 @ 2.12.2010, 13:54) *
а что именно происходит - просто ступор или окошко какое выпрыгивает ?

Функция запускается в дочернем процессе, и соединение создано тоже в дочернем.
А зависают оба процесса.

Хм.. Может потому что есть ещё одно соединение с локальной БД, использующее подключение созданное в главном потоке, а запрос выполняется в дочернем и по какой то причине не закрывается..


Цитата(xls @ 2.12.2010, 15:06) *
Если разрыв соединения будет корректный, т.е. сервер СУБД остановлен, то все будет хорошо - данных не будет вообще.
Если же сервер стоит на другом узле и вы выдерните кабель сетевого соединения...

Ну.. На практике чаще всего бывает второй вариант. Вы будете в шоке, но соединение происходит через gprs и прочие похожие недоинтернеты =)

Автор: xls 6.12.2010, 13:31

Цитата
Функция запускается в дочернем процессе, и соединение создано тоже в дочернем.
А зависают оба процесса.

Суда по тому, как Вы создаете запрос, Вы используете "соединение по умолчанию" и в главном и в дочернем потоке, поэтому при зависании соединения с СУБД в дочернем потоке первое же обращение к данным из того же соединения в главном потоке будет аналогичное зависание.

Автор: Litkevich Yuriy 6.12.2010, 20:53

Цитата(512es @ 2.12.2010, 17:41) *
Функция запускается в дочернем процессе, и соединение создано тоже в дочернем.
вот http://doc.crossplatform.ru/qt/4.4.3/threads.html#threads-and-the-sql-module учли?

Автор: 512es 6.12.2010, 21:17

Цитата(Litkevich Yuriy @ 6.12.2010, 20:53) *
вот http://doc.crossplatform.ru/qt/4.4.3/threads.html#threads-and-the-sql-module учли?


http://www.forum.crossplatform.ru/index.php?showtopic=5092&view=findpost&p=43544

читал, но не учёл. со склайтом работает.. склайт собран с флагом threads хотя наверное это и не правильно, но работает же!..

Цитата(xls @ 6.12.2010, 13:31) *
Цитата
Функция запускается в дочернем процессе, и соединение создано тоже в дочернем.
А зависают оба процесса.

Суда по тому, как Вы создаете запрос, Вы используете "соединение по умолчанию" и в главном и в дочернем потоке, поэтому при зависании соединения...


я наверное вас запутал уже. вообщем, вот так всё устроено:

* главный поток
1) склайт соединение с локальной базой

* дочерний поток
1) то же соединение что в первом потоке, используется совместно.
2) соединение с базой постгреса через медленный инет. используется только в этом потоке. частенько разрывы.

отсюда логично предположить что при разрыве связи зависнет дочерний поток, а главный продолжит работать. но почему то этого не происходит..

может и правда это каким то образом связано с тем, что я шарю одно соединение склайта на 2 потока. но блин, ведь тестировал и много тестировал...

может передавать сигналами данные из дочернего в главный, чтобы записать их в базу? или открыть ещё одно подключение, и при ошибке о том что база занята как то повторять запрос..

или всётаки это из за неправильного закрытия запросов?

Автор: Litkevich Yuriy 6.12.2010, 21:56

Цитата(512es @ 6.12.2010, 23:17) *
но почему то этого не происходит..
дык, тыж соединение главного потока пользуешь, вот главный и занят. Доку прочитал, а делаешь поперёк.

Автор: 512es 7.12.2010, 9:17

Цитата(Litkevich Yuriy @ 6.12.2010, 21:56) *
дык, тыж соединение главного потока пользуешь, вот главный и занят.

В дочернем потоке запросы срабатывают лишь иногда и не блокируют главный поток надолго.

Вот в том то и вопрос:
Как правильно закрывать запросы, чтоб не возникло ситуации когда главный поток подвисает навсегда?

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)