0

「ローカル」と「リモート」の 2 つの 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、32 ビット、Ubuntu 14.04 で見つかりました。Raspberry Pi、Qt 5.6 でもテストされましたが、結果として「セグメンテーション違反」が発生しました。

なにが問題ですか?

main.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();
}
4

1 に答える 1

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 モジュール」リンクの情報はある程度正しいようです。何らかの理由で、「ローカル」接続がまだスレッドから機能していました。

于 2016-06-03T11:20:11.933 に答える