2011-09-27 18 views
5

SqlモジュールがQtのマルチスレッドアプリケーションでどのように動作するかに問題があります。 http://doc.qt.io/qt-5/threads-modules.html#threads-and-the-sql-moduleは、「接続を作成したスレッド内からのみ使用できます」ということを明らかに示しています。 QSqlモジュールとマルチスレッドアプリケーション

ただし、コードのこの作品は、私が作品を書いた:

#include <QCoreApplication> 
#include <QSqlQuery> 
#include <QtConcurrentRun> 

void req() 
{ 
    QSqlQuery q("INSERT INTO users (username) VALUES (\"test\")"); 
} 

void db() 
{ 
    QSqlDatabase _db; 

    _db = QSqlDatabase::addDatabase("QMYSQL"); 
    _db.setDatabaseName("dbname"); 
    _db.setHostName("host"); 
    _db.setUserName("username"); 
    _db.setPassword("password"); 
    if (_db.open()) 
    std::cout << "Ok" << std::endl; 
    else 
    std::cout << "Error" << std::endl; 
} 

int  main(int ac, char **av) 
{ 
    QCoreApplication app(ac, av); 
    QtConcurrent::run(db); 
    sleep(1); 
    QtConcurrent::run(req); 
    return app.exec(); 
} 

私のアプリケーションの設計は、データベースと対話するために複数のスレッドが必要です。 Thread はQtConcurrent :: run()によって生成され、管理されます。

コードのこの部分が私のために行く必要がありますか、それとも私は のトラブルに遭遇するでしょうか?

ヘルプ、ドキュメント、説明は大歓迎です! ありがとうございます。

答えて

6

QSqlQuery creates its own QSqlDatabaseが原因で上記のコードは正常です。 db()によって作成された_dbを参照すると問題になります。欠点は、実際にはdo何もしていないということです。

QSqlDatabaseはQObjectではありませんが、QObjectであるdriverを持っているため、thread affinityです。

QSqlDatabasesのロードを作成するのが禁止されている場合は、独自の接続を維持するworker threadsを作成してください。次に、新しいスレッドを作成するのではなく、新しい接続を作成するのではなく、これらのスレッドにクエリをディスパッチします。

+0

「ダウンサイドは、実際に何もしないことです」とはどういう意味ですか? ?クエリが実行され、エントリが挿入されます。私がうまく理解できれば、QSqlQueryは 'QSqlDatabase :: addDatabase()'によって作成されたデータベースのデータベース設定を使って独自のQSqlDatabaseを作成しますか?それは(オブジェクトのコピーや何かのために)オーバーヘッドが多いことを意味しますか? – Xaqq

+1

QSqlQuery :: QSqlQuery :: QSqlQuery(QString&QSqlDatabase) 'は、' 'db'接続された"コンストラクタ "を使用していないので、' QSqlQuery'オブジェクトもあなたが作成した 'QSqlDatabase'について何も知らない(つまり、クエリに 'db'を作成します)。クエリーをインスタンス化する方法は、 'req()'が呼び出されるたびに、新しい別個のDB接続が作成される/取り除かれることを意味します。どのスレッドセーフですが、潜在的に高価です。 –

+0

もう少しテストを行い、複数のQtConcurent :: run(req)を呼び出すと、テストプログラムがsegfaultになっています。編集:それは、クエリinstanciationはスレッドセーフではないようです。 – Xaqq

関連する問題