首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在多线程程序中正确使用QSqlDatabase

在多线程程序中正确使用QSqlDatabase
EN

Stack Overflow用户
提问于 2013-12-27 01:55:26
回答 2查看 11.5K关注 0票数 19

基于Qt文档:

只能从创建连接的线程中使用连接。不支持在线程之间移动连接或从其他线程创建查询。

困扰我的问题是,当我复制-构造数据库实例时会发生什么。例如,下面是主线程中的代码:

代码语言:javascript
运行
复制
int main(int argc, char** argv) {
...
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "DB1");
    db.setHostName("localhost");
...

下面是worker 线程中的连接

代码语言:javascript
运行
复制
void MyThread::run() {
    QSqlDatabase db(QSqlDatabase::database("DB1"));
    if (db.open()) {
    ...
}

这个线程安全吗?通常,这样的操作在C++中是安全的,但是由于QT使用隐式共享和线程亲和力,所以我不再确定。

他们说:连接只能从创建它的线程中使用,但这意味着什么呢?是QSqlDatabase::addDatabase点,其中创建了 connection ,或者在调用 open() 函数时实际使用了它。E 215

更新:

在Laszlo的回答之后,并最终查看了Qt源代码之后,我必须说,Qt的这一部分的设计在我看来是有缺陷的。

如果我正确理解,QSqlDatabase在幕后使用隐式共享,但不幸的是它不是真正的隐式共享,因为QSqlDatabase实例的复制构造函数在需要时不会创建共享数据的新实例。更糟糕的是,您不能创建临时连接,而是必须使用静态方法addDatabase/removeDatabase,在这种情况下,您必须同步线程以避免名称冲突。

当然,这使得在QtConcurrent中使用QtConcurrent非常困难,特别是如果连接应该隐藏在某些抽象的后面。由于我们不知道将在哪个线程上运行代码,所以不能在两个调用之间保持连接打开。如果我们想要生成动态的任务数,我们需要确保任务不使用相同的数据库名称。

所有这些让我想知道设计目标,以及隐式共享是否适合这种特殊情况。IMHO,更好的解决方案是让复制构造函数真正地完成它,并为您创建一个连接副本。那些不希望拥有私有/临时副本的用户仍然可以使用addDatebase/removeDatabase,在这种情况下,需要修改方法数据库()以返回引用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-27 02:04:53

他们说:连接只能在创建连接的线程中使用,但这意味着什么呢?是QSqlDatabase::addDatabase点,在这里创建连接,或者在调用open()函数时实际使用。

前者。详细信息请参见文档

QSqlDatabase类表示到数据库的连接。 QSqlDatabase类提供了一个通过连接访问数据库的接口。QSqlDatabase的一个实例表示连接。该连接通过从QSqlDriver派生的受支持的数据库驱动程序之一提供对数据库的访问。或者,您可以从QSqlDriver中子类您自己的数据库驱动程序。有关详细信息,请参阅如何编写您自己的数据库驱动程序。 通过调用一个静态的QSqlDatabase()函数来创建一个连接(即addDatabase的一个实例).

最后这句话应该能澄清你的顾虑。

票数 6
EN

Stack Overflow用户

发布于 2015-09-11 09:15:38

您可以使用QSqlDatabase::cloneDatabase获取数据库的“真实”副本,该副本可以在任何线程中打开。

您需要在初始化克隆数据库的线程中这样做,但是您可以将未打开的数据库移动到任何线程,并在那里使用它。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20793689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档