基于Qt文档:
只能从创建连接的线程中使用连接。不支持在线程之间移动连接或从其他线程创建查询。
困扰我的问题是,当我复制-构造数据库实例时会发生什么。例如,下面是主线程中的代码:
int main(int argc, char** argv) {
...
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "DB1");
db.setHostName("localhost");
...下面是worker 线程中的连接
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,在这种情况下,需要修改方法数据库()以返回引用。
发布于 2013-12-27 02:04:53
他们说:连接只能在创建连接的线程中使用,但这意味着什么呢?是QSqlDatabase::addDatabase点,在这里创建连接,或者在调用open()函数时实际使用。
前者。详细信息请参见文档:
QSqlDatabase类表示到数据库的连接。 QSqlDatabase类提供了一个通过连接访问数据库的接口。QSqlDatabase的一个实例表示连接。该连接通过从QSqlDriver派生的受支持的数据库驱动程序之一提供对数据库的访问。或者,您可以从QSqlDriver中子类您自己的数据库驱动程序。有关详细信息,请参阅如何编写您自己的数据库驱动程序。 通过调用一个静态的QSqlDatabase()函数来创建一个连接(即addDatabase的一个实例).
最后这句话应该能澄清你的顾虑。
发布于 2015-09-11 09:15:38
您可以使用QSqlDatabase::cloneDatabase获取数据库的“真实”副本,该副本可以在任何线程中打开。
您需要在初始化克隆数据库的线程中这样做,但是您可以将未打开的数据库移动到任何线程,并在那里使用它。
https://stackoverflow.com/questions/20793689
复制相似问题