QSqlDatabase:无法使用来自 QThread 的连接

Posted

技术标签:

【中文标题】QSqlDatabase:无法使用来自 QThread 的连接【英文标题】:QSqlDatabase: unable to use connection from QThread 【发布时间】:2016-06-02 15:11:13 【问题描述】:

我有两个 QSqlDatabase 数据库连接,“本地”和“远程”。我有一个使用两个连接的函数(从本地数据库获取数据并发送到远程数据库)。当我从 QThread 类运行此函数时,本地连接有效(我得到了预期的数据),但远程连接失败。但是如果我在 QThread 类之外(在 main() 中)运行这个函数,两个连接都可以工作。

当我尝试打开连接时,远程连接失败并显示错误消息:“QSqlDatabasePrivate::database: 无法打开数据库:Qmysql: 无法连接”。在此之前,我测试了连接是否有效(isValid())并且它是好的。我还检查了连接是否已经打开,但不是。

我也找到了这些信息,但由于“本地”连接从线程工作,这可能不是问题:

线程和 SQL 模块 只能在创建它的线程内使用连接。不支持在线程之间移动连接或从不同线程创建查询。 http://doc.qt.io/qt-5/threads-modules.html#threads-and-the-sql-module

在 Qt 5.5.1, 32bit, Ubuntu 14.04 中发现错误。还在 Raspberry Pi、Qt 5.6 上进行了测试,但结果是“分段错误”。

怎么了?

ma​​in.c

main()

  DataHandler dh();
  DataHandlerThread dht(&dh); //pointer to dh to get access to dh functions from the thread

  //here I run dh.foo() or dht.run(), never both functions
  dh.foo();
  dht.run();
  ...

datahandler.cpp

DataHandler::DataHandler()

  m_dbLocal = QSqlDatabase::addDatabase("QMYSQL", "local");
  m_dbLocal.setHostName("localhost");
  ...

  m_dbRemote = QSqlDatabase::addDatabase("QMYSQL", "remote");
  m_dbRemote.setHostName(...);
  ...


DataHandler::foo()

  qDebug() << QSqlDatabase::connectionNames(); //always ("remote", "local")
  m_dbLocal.isValid(); //always true
  m_dbLocal.open(); //always true

  m_dbRemote.isValid(); //always true

  //true if foo() is called from main using dm.foo()
  //QSqlDatabasePrivate::database: unable to open database: " QMYSQL: Unable to connect" if called from main using dmt.run()
  m_dbRemote.open(); 

datahandlerthread.h

class DataHandlerThread : public QThread

    Q_OBJECT
public:
    explicit DataHandlerThread(DataHandler* dh);

private:
    void run() Q_DECL_OVERRIDE;

    DataHandler* m_dh;

;

datahandlerthread.cpp

DataHandlerThread::DataHandlerThread(DataHandler* dh)

    m_dh = dh;


void DataHandlerThread::run()

    m_dh->foo();

【问题讨论】:

或许贴出代码有助于发现问题? 帖子更新代码 【参考方案1】:

我找到了解决问题的方法。解决方案是在 DataHandlerThread 构造函数中创建本地和远程连接的新实例:

datahandlerthread.cpp

DataHandlerThread::DataHandlerThread(DataHandler* dh)

  m_dh = dh;
  m_dbLocal = QSqlDatabase::addDatabase("QMYSQL", "local_thread");
  m_dbLocal.setHostName("localhost");
  ...

  m_dbRemote = QSqlDatabase::addDatabase("QMYSQL", "remote_thread");
  m_dbRemote.setHostName(...);
  ...

据我了解,这些新实例也可以通过使用 QSqlDatabase::cloneDatabase() 创建并将这些新实例传递给 DataHandlerThread 构造函数(未测试)。

因此,“线程和 SQL 模块”链接中的信息似乎有些正确。由于某种原因,“本地”连接仍然可以从线程工作。

【讨论】:

以上是关于QSqlDatabase:无法使用来自 QThread 的连接的主要内容,如果未能解决你的问题,请参考以下文章

使用 macdeployqt 构建 QSqlDatabase 的 Qt 应用程序无法正常工作

QSqlDatabase-SQLite无法在开机自启动时加载数据?

PyQt5 QSqlDatabase 在没有任何文本错误的情况下无法打开

无法将值插入 QSqlDatabase

在多个 qt 线程中使用单个 QSqlDatabase 连接

QSqlDatabase: QMYSQL driver not loaded