我有一个代码,可以对数据库执行3次异步生成操作。如果我运行3个异步操作,此代码会崩溃,但如果它只有一个没有问题。如何在SQLite上组织多线程操作?我尝试过QMutex.lock,但它没有用。
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtConcurrent/QtConcurrentRun>
#include <database.h>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Database *db0=new Database();
Database *db1=new Database();
Database *db2=new Database();
QString param0="Select LastUpdateDate From TableLastUpdateLog Where TableName='T1'";
QString param1="Select LastUpdateDate From TableLastUpdateLog Where TableName='T2'";
QString param2="Select LastUpdateDate From TableLastUpdateLog Where TableName='T3'";
QtConcurrent::run(db0,&Database::Select,param0);
QtConcurrent::run(db1,&Database::Select,param1);
QtConcurrent::run(db2,&Database::Select,param2);
return app.exec();
}
database.cpp
void Database::Select(QString query) {
m_db=QSqlDatabase::addDatabase("QSQLITE","myconn");
m_db.setDatabaseName("./mytask.db");
bool result=m_db.open();
if(result==false)
qDebug()<<"Failed";
else
{
qDebug()<<"Connection is Success";
m_qry=new QSqlQuery(m_db);
m_qry->exec("PRAGMA foreign_keys = ON;");
m_qry->exec("DSQLITE_THREADSAFE=2");
m_qry->prepare(query);
if(m_qry->exec()!=true)
{
qDebug()<<"Query Failed:"<<m_qry->lastError();
qDebug()<<m_qry->lastQuery();
}
else
{
QSqlRecord rec=m_qry->record();
while(m_qry->next())
{
qDebug()<<m_qry->value("LastUpdateDate").toDateTime();
}
}
}
m_db.close();
m_db.removeDatabase("myconn");
//mutex.unlock();
}
答案 0 :(得分:0)
您的代码崩溃是因为您仍然 使用相同的连接从每个线程访问数据库 。在Qt中,连接由它们的名称标识,即值“myconn”传递给addDatabase
。
不仅Qt行为不端,而且sqlite驱动程序也是如此。来自Qt docs
Warning: If you add a connection with the same name as an existing connection,
the new connection replaces the old one.
您的声明SQLITE_THREADSAFE=2
允许多线程,只要no two threads attempt to use the same database connection,情况并非如此。
解决方案是为每个对象提供不同的连接名称。