Russian Qt Forum
Апрель 29, 2024, 08:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Работа в SQLite в многопоточном приложении  (Прочитано 27254 раз)
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #15 : Декабрь 11, 2016, 10:42 »

Значит либо сейчас стало можно, либо ты просто не попадал на 2 запроса изменения из разных потоков одновременно.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #16 : Декабрь 11, 2016, 10:54 »

Цитировать
Значит либо сейчас стало можно, либо ты просто не попадал на 2 запроса изменения из разных потоков одновременно.

Не, SQLite разруливает все сам, т.к. по умолчанию он собирается с: SQLITE_THREADSAFE=1, который просто ставит запросы от разных потоков в очередь..
Типо они выполняются последовательно в итоге все-равно (как я понял), т.е. выигрыш только в том, что ГУЙ не тормозит.

Цитировать
SQLITE_THREADSAFE=<0 or 1 or 2>

    This option controls whether or not code is included in SQLite to enable it to operate safely in a multithreaded environment. The default is SQLITE_THREADSAFE=1 which is safe for use in a multithreaded environment. When compiled with SQLITE_THREADSAFE=0 all mutexing code is omitted and it is unsafe to use SQLite in a multithreaded program. When compiled with SQLITE_THREADSAFE=2, SQLite can be used in a multithreaded program so long as no two threads attempt to use the same database connection (or any prepared statements derived from that database connection) at the same time.

    To put it another way, SQLITE_THREADSAFE=1 sets the default threading mode to Serialized. SQLITE_THREADSAFE=2 sets the default threading mode to Multi-threaded. And SQLITE_THREADSAFE=0 sets the threading mode to Single-threaded.

    The value of SQLITE_THREADSAFE can be determined at run-time using the sqlite3_threadsafe() interface.

    When SQLite has been compiled with SQLITE_THREADSAFE=1 or SQLITE_THREADSAFE=2 then the threading mode can be altered at run-time using the sqlite3_config() interface together with one of these verbs:

        SQLITE_CONFIG_SINGLETHREAD
        SQLITE_CONFIG_MULTITHREAD
        SQLITE_CONFIG_SERIALIZED

    The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags to sqlite3_open_v2() can also be used to adjust the threading mode of individual database connections at run-time.

    Note that when SQLite is compiled with SQLITE_THREADSAFE=0, the code to make SQLite threadsafe is omitted from the build. When this occurs, it is impossible to change the threading mode at start-time or run-time.

    See the threading mode documentation for additional information on aspects of using SQLite in a multithreaded environment.

Записан

ArchLinux x86_64 / Win10 64 bit
rudireg
Гость
« Ответ #17 : Декабрь 11, 2016, 10:55 »

Цитировать
С SQLite нельзя работать в несколько потоков
Неужли?
Вообще-то нужно просто создавать соединения в разных потоках.. Этого достаточно, ЕМНИП.
Я попробывал делать соединение в разных потоках и это не помогло.
Ниже приведу код простого приложения.
Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке.
QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970).
Cannot move to target thread (0x5e4fa8)


Я даже пытался понять на какой именно строке кода вылетает данная ошибка, как мне показалось после выполнения строки
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect);

ниже код
mainwindow.h
Код
C++ (Qt)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QThread>
#include "database.h"
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   MainWindow(QWidget *parent = 0);
   ~MainWindow();
 
   void startFirstThread();
   void stratSecondThread();
};
 
#endif // MAINWINDOW_H
 

mainwindow.cpp
Код
C++ (Qt)
#include "mainwindow.h"
//-------------------------------------------------
MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent)
{
   this->startFirstThread();
   this->stratSecondThread();
}
//-------------------------------------------------
MainWindow::~MainWindow()
{
}
//-------------------------------------------------
void MainWindow::startFirstThread()
{
   QThread*  thread = new QThread;
   DataBase* db     = new DataBase;
 
   QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessFirst()));
   QObject::connect(db, SIGNAL(finished()), thread, SLOT(quit()));
   QObject::connect(db, SIGNAL(finished()), db, SLOT(deleteLater()));
   QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
 
   db->moveToThread(thread);
   thread->start();
}
//-------------------------------------------------
void MainWindow::stratSecondThread()
{
   QThread*  thread = new QThread;
   DataBase* db     = new DataBase;
 
   QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessSecond()));
   QObject::connect(db, SIGNAL(finished()), thread, SLOT(quit()));
   QObject::connect(db, SIGNAL(finished()), db, SLOT(deleteLater()));
   QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
 
   db->moveToThread(thread);
   thread->start();
}
//-------------------------------------------------
 

database.h

Код
C++ (Qt)
#ifndef DATABASE_H
#define DATABASE_H
 
#include <QObject>
#include <QtSql>
 
class DataBase : public QObject
{
   Q_OBJECT
public:
   explicit DataBase(QObject *parent = 0);
 
private:
   QString nameConnect;
   QString lastError;
   QSqlQuery* qDb;
 
   bool init(QString tableName);
 
signals:
   void finished();
 
public slots:
   void ProcessFirst();
   void ProcessSecond();
};
 
#endif // DATABASE_H
 


database.cpp

Код
C++ (Qt)
#include "database.h"
//----------------------------------------------------------
DataBase::DataBase(QObject *parent) : QObject(parent)
{
   qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));
}
//----------------------------------------------------------
//Инициализация
bool DataBase::init(QString tableName)
{
   this->nameConnect = QString("%1%2").arg(tableName).arg(qrand());
 
   QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect);
   db.setDatabaseName(tableName);
   db.setHostName("127.0.0.1");
   db.setUserName("rudi");
   db.setPassword("rudi");
 
   //Open
   if(!db.open()) {
       this->lastError = QString("Cannot open dbBlackList database: %1").arg(db.lastError().text());
       qDebug() << this->lastError;
       return false;
   }
 
   this->qDb = new QSqlQuery(QSqlDatabase::database(this->nameConnect));
   if(!this->qDb)
       return false;
 
   return true;
}
//----------------------------------------------------------
void DataBase::ProcessFirst()
{
   this->init("First");
   emit finished();
}
//----------------------------------------------------------
void DataBase::ProcessSecond()
{
   this->init("Second");
   emit finished();
}
//----------------------------------------------------------
 
« Последнее редактирование: Декабрь 11, 2016, 11:08 от rudireg » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #18 : Декабрь 11, 2016, 12:37 »

Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #19 : Декабрь 11, 2016, 12:49 »

Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued

По умолчанию они авто, тип соединения определяется в момент эмита, а не коннекта.
Дело не в этом.
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #20 : Декабрь 11, 2016, 13:11 »

Сначала делай moveToThread, а потом уже конекты. У тебя коннекты с Direct соединились, а надо Queued

По умолчанию они авто, тип соединения определяется в момент эмита, а не коннекта.
Дело не в этом.
Хм. Не знал. Всегда думал, что на этапе связки определяется.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #21 : Декабрь 11, 2016, 13:19 »

А. Есть переменная окружения QT_FATAL_WARNINGS или как-то так, если ее поставить в 1 то программа упадет на этом ворнинге и можно будет получить стектрейс.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #22 : Декабрь 11, 2016, 13:55 »

Цитировать
Я попробывал делать соединение в разных потоках и это не помогло.
Ниже приведу код простого приложения.
Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке.
QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970).
Cannot move to target thread (0x5e4fa8)

Так дело то в Вашем коде, а не в SQLite.  Улыбающийся
Записан

ArchLinux x86_64 / Win10 64 bit
rudireg
Гость
« Ответ #23 : Декабрь 11, 2016, 14:02 »

Цитировать
Я попробывал делать соединение в разных потоках и это не помогло.
Ниже приведу код простого приложения.
Ошибка не вылетает сразу... нужно несколько раз запускать и закрывать приложение, и гдето 1 раз и трех или четырех попыток запуска приложения вылазит сообщения об ошибке.
QObject::moveToThread: Current thread (0x6049a8) is not the object's thread (0x604970).
Cannot move to target thread (0x5e4fa8)

Так дело то в Вашем коде, а не в SQLite.  Улыбающийся

Буду раз если укажите на ошибку
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #24 : Декабрь 11, 2016, 15:50 »

Для начала нужно вывести идентификаторы QThread::id из каждого метода и смотреть что не так.
Должно быть так, чтобы все методы/слоты класса DataBase выполнялись в контексте того треда в который этот объект перемещен.
Записан

ArchLinux x86_64 / Win10 64 bit
qate
Супер
******
Offline Offline

Сообщений: 1175


Просмотр профиля
« Ответ #25 : Декабрь 12, 2016, 09:34 »

насколько я могу понять код, который лучше былобы выложить готовым проектом ибо лень его самому делать, метод инициализации БД будет вызван в GUI потоке,отя предполагалось в новом, см.
QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessFirst()));

для выяснения кто кинул warning можно повесить свой обработчик qInstallMessageHandler и так точкой останова иметь полный стек
Записан
rudireg
Гость
« Ответ #26 : Декабрь 12, 2016, 15:57 »

насколько я могу понять код, который лучше былобы выложить готовым проектом ибо лень его самому делать, метод инициализации БД будет вызван в GUI потоке,отя предполагалось в новом, см.
QObject::connect(thread, SIGNAL(started()), db, SLOT(ProcessFirst()));

для выяснения кто кинул warning можно повесить свой обработчик qInstallMessageHandler и так точкой останова иметь полный стек
GUI  делает коннект, что как только запущен поток, то вызывается инициализация.
Инициализация БД происходит не в GUI  а в дочернем потоке, и там же БД будет использоваться.
Прикладываю готовый проект
http://mamba.apibot.ru/tmp/sqlite.rar
« Последнее редактирование: Декабрь 12, 2016, 15:59 от rudireg » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #27 : Декабрь 12, 2016, 16:11 »

У тебя пример некорректен, ты забыл db.open() сделать. Добавил - УМВР, никаких ворнингов.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
rudireg
Гость
« Ответ #28 : Декабрь 12, 2016, 17:09 »

У тебя пример некорректен, ты забыл db.open() сделать. Добавил - УМВР, никаких ворнингов.

все корректно.... db.open()  даже не нужно вызывать,,
ибо даже выполняя эту строку
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", this->nameConnect);
уже будет ошибка.
так что open  не обязательно, ибо ошибка идет до open


ЧТо такое - УМВР Непонимающий
« Последнее редактирование: Декабрь 12, 2016, 17:31 от rudireg » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #29 : Декабрь 12, 2016, 18:51 »

УМВР - У Меня Все Работает. С гуглом надо дружить, камрад. Улыбающийся
Я собрал и запустил - ни одной ошибки в консоль не выдало.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.199 секунд. Запросов: 22.