Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [QT] Использование QSqlQuery в QThread


Автор: ecspertiza 27.4.2009, 15:06
Вообщем возник такой вопрос можно ли(я думаю что можно) использовать QSqlQuery в QThread , я делаю вот так

Код

class Buffering : public QThread
{

public:
    Buffering(int _catalogue_id,QObject *parent);

    void setCatalogue_id(int);
    void run();


    private:
        int catalogue_id;
        QMutex mutex;
 };


Код

Buffering::Buffering(int _catalogue_id,QObject *parent)
        :QThread(parent)
{
    catalogue_id = _catalogue_id;
}

void Buffering::setCatalogue_id(int index)
{
    catalogue_id = index;
}

void Buffering::run()
{
    qDebug() << "start thread";
    mutex.lock();
    QSqlQuery threadQuery;

    if (!threadQuery.exec("select * from object"))
        qDebug() << "buffering error" << threadQuery.lastError();
    else
        qDebug() << "buffering not error" << threadQuery.lastError();
    mutex.unlock();
    qDebug() << "end thread";
}


создание потока

Код

    if ((QSqlDatabase::database().isOpen() == true) && (index != 0))
    {
        Buffering *thread = new Buffering(index,this);
        connect(thread,SIGNAL(finished()),thread,SLOT(terminate()));
        thread->start();
    }


при выполнении потока софт постоянно зависает, в чём могут быть грабли, с потоками особо незнаком каюсь, читаю соответствующую литературу но пока ничего не могу понять.

Автор: null56 27.4.2009, 16:11
Код

 mutex.lock();

это зачем?
Код

 if ((QSqlDatabase::database().isOpen() == true) && (index != 0))

Ты создаешь соединение в другом потоке, не уверен, что это правильно
Код

public:
         void run();

Компилятор это пропустил? на сколько мне известно, функция должна быть protected...
Код

connect(thread,SIGNAL(finished()),thread,SLOT(terminate()));

Это что такое??? по заверщению завершить???? висит из -за функции terminate(), ее лучше не использовать

Автор: ecspertiza 27.4.2009, 16:17
Код

connect(thread,SIGNAL(finished()),thread,SLOT(terminate()));


насколько я понял по завершению поток шлёт сигнал finished(), а terminate() убивает этот поток дабы он не висел.

нашёл в чём были грабли, но незнаю это правильно или нет.

я в потоке создаю ещё одно соединение с базой данных и с ним работаю и вроде всё нормально отрабатывает)))

Автор: null56 27.4.2009, 16:25
Цитата(ecspertiza @ 27.4.2009,  16:17)
насколько я понял по завершению поток шлёт сигнал finished(), а terminate() убивает этот поток дабы он не висел.

поток завершается после того, как отрабатывает функция run(), после выхода из нее, потока больше нет...
Цитата

Returning from this method will end the execution of the thread.

Автор: ecspertiza 27.4.2009, 16:33
спасибо, в общем вопрос закрыт)))

Автор: Acer 27.4.2009, 22:26
Цитата(null56 @ 27.4.2009,  15:11)
Код

public:
         void run();

Компилятор это пропустил? на сколько мне известно, функция должна быть protected...

чиво?
Она в QThread является protected(еще и virtual), а вот в дочернем классе мы ее переопределяем как public.

Автор: null56 28.4.2009, 10:03
Acer, да, это я не в кассу сказал, сам не понял зачем...

Автор: weldpua2008 29.4.2009, 09:47
Цитата(null56 @ 27.4.2009,  16:11)
Код

 if ((QSqlDatabase::database().isOpen() == true) && (index != 0))

Ты создаешь соединение в другом потоке, не уверен, что это правильно

http://doc.crossplatform.ru/qt/4.5.0/threads.html#threads-and-the-sql-module
Цитата

Потоки и модуль SQL

Соединение может использоваться только внутри создавшего его потока. Перемещение соединений между потоками и создание запросов в другой поток не поддерживается.

Кроме того, используемые драйверами QSqlDriver сторонние библиотеки могут наложить дополнительные ограничения на использование модуля SQL в многопоточной программе. За дополнительной информацией обращайтесь к руководству по клиенту вашей базы данных.

http://habrahabr.ru/blogs/qt_software/52536/
Цитата

Все кто разрабатывают приложения на Qt, рано или поздно сталкиваются с работой с БД в многопоточном окружении.И если невнимательно читать Ассистант, то можно натолкнуться на одни очень интересные грабли....

Описание окружения
Рассмотрим типовую проблему. Вы пишите приложение, работающее с бд, при этом вам необходимо обращаться к БД из нескольких потоков (не важно одновременно или нет). Например такое бывает если вы пишите серверную часть некоего приложения или просто у вас есть логгирующий поток с записью в БД.

Описание граблей


Если внимательно читать ассистант (то есть не только описание классов, но и общие статьи), то мы увидим следующую надпись в описании многопоточного программирования под Qt: «Подключение может быть использовано только тем потоком, который его создал....

Объяснение граблей


Таким образом, запланированный нами банальный мутекс на подключение к БД работать к сожалению не будет. Так же (если нам не нужно все время делить подключение между несколькими потоками, а в первой половине работы программы его должен использовать один поток, а потом другой) не будет и работать метод moveToThread(), так хорошо показывающий себя при работе например с сокетами.

Попытка поразмыслить над проблемой

Ок, мы не можем делить одно подключение между несколькими потоками. Но как мы можем обойти эту проблему? Я вижу два пути:

   1. Не париться и делать в каждом потоке свое подключение
   2. Обратиться к старому доброму паттерну Singleton


Ну и дальше можно почитать smile

Автор: gmurik2 7.10.2010, 09:35
День добрый! Делаю все как там написано, пробую компилировать gcc, получаю в консоль
Код

C:\Qt\2010.05\test_build-desktop/../test/main.cpp:7: undefined reference to `DatabaseAccessor::dbHost'
C:\Qt\2010.05\test_build-desktop/../test/main.cpp:8: undefined reference to `DatabaseAccessor::dbName'
C:\Qt\2010.05\test_build-desktop/../test/main.cpp:9: undefined reference to `DatabaseAccessor::dbUser'
C:\Qt\2010.05\test_build-desktop/../test/main.cpp:10: undefined reference to `DatabaseAccessor::dbPass'


в чем могут быть грабли?

Автор: ecspertiza 7.10.2010, 21:17
gmurik2, выкладывай весь код, как вариант ты либо не описал ф-ции на которые ругается компилятор, либо не подключил какую то библиотеку.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)