首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QMYSQLResult::清理:无法释放语句句柄

QMYSQLResult::清理:无法释放语句句柄
EN

Stack Overflow用户
提问于 2015-07-27 15:31:43
回答 1查看 1K关注 0票数 0

我试图使用线程从MySQL数据库中获取数据,但在调用:

代码语言:javascript
复制
QThread* thread = new QThread;
Beacon *beacon = new Beacon(m_db, begin, end);
beacon->moveToThread(thread);
connect(beacon, &Beacon::values, this, &Tm::insertRow);
connect(beacon, &Beacon::finished, thread, &QThread::quit);
connect(beacon, &Beacon::finished, beacon, &Beacon::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
connect(thread, &QThread::started, beacon, &Beacon::executeQuerySmooth);
connect(beacon, &Beacon::finished, this, &Tm::finished);
thread->start();

我得到:

代码语言:javascript
复制
QMYSQLResult::cleanup: unable to free statement handle

下一次尝试使用我得到的连接:

代码语言:javascript
复制
QSqlError("2006", "QMYSQL: Unable to execute query", "MySQL server has gone away")

可能会发生什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-27 17:23:04

您只能使用创建它的线程(参考文献)的连接,或者通常只能从一个线程使用连接。

你可以采取两种方法:

  1. 在一个专用线程中维护数据库连接,并从那里使用它。无论如何,使用短命线程是一种过早的悲观,所以这是一种糟糕的方法。
  2. 将工作线程之间的数据库连接从线程池中移动。使用QtConcurrent::run在线程池中的线程上运行函子。

注意:Beacon::Beacon(...) 构造函数不能使用数据库,它只能存储对它的引用/指针!

有关这个答案的更多信息,请参见postCall

代码语言:javascript
复制
template <typename T>
void postCall(QThread * thread, T && functor) {
   QObject source;
   QObject::connect(&source, &QObject::destroyed,
                    QEventDispatcher::instance(thread), std::forward(functor));
}

线程池的工人

代码语言:javascript
复制
class Tm : public QObject {
  Q_OBJECT
  QMutex m_dbMutex;
  QSqlDatabase m_db;
  Q_SIGNAL void openFailed();
  Q_SIGNAL void openSucceeded();
public:
  void openConnection() {
    QMutexLocker lock(&m_dbMutex);
    m_db.addDatabase("QSQLITE");
    ... // set database's properties
    m_db.moveToThread(0); // we don't know what thread it will be used in
    lock.unlock();
    QtConcurrent::run([this]{
      QMutexLocker lock(&m_dbMutex);
      m_db.moveToThread(QThread::currentThread());
      bool rc = m_db.open();
      if (rc) {
        m_db.moveToThread(0);
        emit openSucceeded();
      } else {
        m_db.moveToThread(this->thread());
        emit openFailed();
      }
    });
  }
  void beaconate() {
    ...
    QSharedPointer<Beacon> beacon(new Beacon(&m_db, begin, end));
    connect(beacon, &Beacon::values, this, &Tm::insertRow);
    connect(beacon, &Beacon::finished, this, &Tm::finished);
    beacon->setMoveToThread(0);
    QtConcurrent::run([beacon]{
      beacon->moveToThread(QThread::currentThread());
      QMutexLocker lock(&m_dbMutex);
      m_db.moveToThread(QThread::currentThread());
      QEventLoop loop; // only if Beacon needs one
      connect(beacon, &Beacon::finished, &loop, &QEventLoop::quit);
      beacon->executeQuerySmooth();
      loop.exec();
      m_db.moveToThread(0);
    });
  }
  ~Tm() {
    QMutexLocker lock(&m_dbMutex);
    m_db.moveToThread(thread());
  }
  ...
};

专用螺纹

代码语言:javascript
复制
class Thread : public QThread
{ using QThread::run; public: ~Thread() { quit(); wait(); } };

class Tm : public QObject {
  Q_OBJECT
  QSqlDatabase m_db;
  Thread m_dbThread; // must be declared after m_db, so that it's destructed prior to m_db
  Q_SIGNAL void openFailed();
  Q_SIGNAL void openSucceeded();
public:
  Tm(QObject * parent = 0) : QObject(parent) {
    m_dbThread.start();
  }
  void openConnection() {
    m_db.addDatabase("QSQLITE");
    ... // set database's properties
    m_db.moveToThread(&m_dbThread);
    postCall(&m_dbThread, [this]{
      if (! m_db.open()) {
        m_db.moveToThread(this->thread());
        emit openFailed();
      } else
        emit openSucceeded();
    });
  }
  void beaconate() {
    ...
    auto beacon = new Beacon(&m_db, begin, end);
    beacon.moveToThread(&m_dbThread);
    connect(beacon, &Beacon::values, this, &Tm::insertRow);
    connect(beacon, &Beacon::finished, beacon, &Beacon::deleteLater);
    connect(beacon, &Beacon::finished, this, &Tm::finished);
    postCall(&m_dbThread, [beacon]{ beacon->executeQuerySmooth(); });
  }
  ~Tm() {
    // Destructing objects living in other threads is undefined behavior
    postCall(&m_dbThread, [this]{ 
      if (m_db.thread() == QThread::currentThread())         
        m_db.moveToThread(thread());
    });
  }
  ...
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31657201

复制
相关文章

相似问题

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