1

qtconcurrent::run()オブジェクトを介してメンバー関数を呼び出すのと同じくらい私の呼び出しが遅いのはなぜですか??

(例:QtConcurrent::run(&db, &DBConnect::loadPhoneNumbers)を呼び出すのと同じくらい遅いdb.loadPhoneNumbers())

詳細な説明については、以下をお読みください

QtConcurrent::runSQLデータベーステーブルに送信されるデータを高速化するために、スレッドを作成しようとしています。QMapであるメンバー変数を取得し、それを繰り返して各キーと値をデータベースに送信しています。

QtConcurrent::run() 呼び出しのメンバー関数:

void DBConnect::loadPhoneNumbers()
{

//m_phoneNumbers is a private QMap member variable in DBConnect
qDebug() << "\t[!] Items to send: " << m_phoneNumbers.size();

QSqlQuery query;
qDebug() << "\t[!] Using loadphonenumbers thread: " << QThread::currentThread();
qDebug() << "\t[!] Ideal Num of Threads: " << QThread::idealThreadCount();

bool isLoaded = false;

QMap<QString,QString>::const_iterator tmp = m_phoneNumbers.constBegin();

while(tmp != m_phoneNumbers.constEnd())
{
    isLoaded = query.exec(QString("INSERT INTO "+m_mtable+" VALUES('%1','%2')").arg(tmp.key()).arg(tmp.value()));

    if(isLoaded == false)
    {
        qDebug() << "\r\r[X] ERROR: Could\'t load number " << tmp.key() << " into table " << m_mtable;
        qDebug() << query.lastError().text();
    }

    tmp++;
}

}

スレッドを呼び出す main.cpp セクション

DBConnect db("QODBC", myINI.getSQLServer(),C_DBASE,myINI.getMTable(), myINI.getBTable());
db.startConnect();

//...more code here

     qDebug() << "\n[*] Using main thread: " << QThread::currentThread() << endl;

         //....two qtconcurrent::run() threads started and finished here (not shown)

         qDebug() << "\n[*] Sending numbers to Database...";
         QFuture<void> dbFuture = QtConcurrent::run(&db, &DBConnect::loadPhoneNumbers);
         dbFuture.waitForFinished();

私の状況理解

私の理解では、このスレッドはメインスレッドとは別のスレッドの新しいプールで実行されます。私が見ているのはそうではありません(データベースのこの呼び出しの前に、他に2つの QtConcurrent::run() 呼び出しがあることに注意してください。データベース呼び出しを続行する前に、すべて終了する必要があります)

QtConcurrent::map() / mapped() を使用することを考えましたが、QMap で適切に動作させることができませんでした。(どちらにも役立つ例が見つかりませんでしたが、それは問題ではありません...なぜ私がそれを使用しなかったのか誰かが尋ねた場合の参考までに)

何が起こっているのかを調べるためにいくつかの「デバッグ」作業を行ってきました。私のテストでは、QThread::currentThread() を使用して、現在呼び出しを行っているスレッドを見つけます。これが、私のプログラムのさまざまなスレッドで起こっていることです。(すべての qtconcurrent::run() 呼び出しは main.cpp FYI で行われます...それが違いを生むかどうかはわかりません)

Check what is main thread: on QThread(0x5d2cd0)
Run thread 1: on QThread(0x5dd238, name = "Thread (pooled)")
Run thread 2: on QThread(0x5d2cd0)
Run thread 3 (loadPhoneNumbers function): on QThread(0x5d2cd0)

上記のように、最初のqtconcurrent::run()呼び出し以外はすべてメイン スレッド上にあります (oO)

質問:

私の理解では、すべてのスレッド (all qtconcurrent::run) は独自のスレッド上にある必要があります (最初のスレッドのみ)。それは本当ですか、それとも何か不足していますか?

次に、私の loadPhoneNumebrs() メンバー関数はスレッドセーフですか?? (私が見ることができるものから何も変更していないので)

最大の疑問:loadPhoneNumbers() qtconcurrent::runメンバー関数を呼び出したときと同じよう に呼び出しが遅いのはなぜですか? (例: db.loadPhoneNumbers()qtconcurrent::run() バージョンと同じくらい遅い)

どんな助けでも大歓迎です!

4

2 に答える 2

2

スレッドは魔法のように物事をスピードアップするのではなく、バックグラウンドで起こっている間、他のことを続けることができるようにするだけです。に電話をかけるとwaitForFinished()、電話番号の読み込みスレッドが終了するまでメインスレッドは続行されないため、基本的にその利点は無効になります。実装によってはcurrentThread()、待機がすでに発生しているため、メインと同じように表示されている場合があります。

おそらく速度の点でより重要なのは、値ごとに個別のクエリではなく、リスト内のすべての値を挿入する単一のクエリを作成することです。

于 2012-12-12T00:30:34.130 に答える
1

QtSqlのドキュメントによると:

接続は、それを作成したスレッド内からのみ使用できます。スレッド間の接続の移動や、別のスレッドからのクエリの作成はサポートされていません。

ODBC自体が単一のODBCハンドルへのマルチスレッドアクセスをサポートしているため、とにかく機能します。ただし、使用している接続は1つだけなので、すべてのクエリは、スレッドが1つしかないかのようにODBCによってシリアル化される可能性があります(たとえば、OracleのODBCドライバーの機能を参照してください)。

waitForFinished()stealRunnable()その名前が示すように、キューからまだ開始されていないタスクをQFuture取得し、現在のスレッドで実行するプライベート関数を呼び出します。

于 2012-12-12T19:47:35.537 に答える