4

QObjectそれぞれ個別の を含む3 つのオブジェクト (から継承) がありますstd::list。各オブジェクトはメイン GUI スレッドで作成され (親なし)、独自のスレッドにプッシュされます (Qt を使用QObject::moveToThread())。

各スレッドは gui に接続され、メッセージは異なるスレッド間でデータとともに送信されます。各スレッドは、基本的に独自のリストを処理します。例えば:

Obj 1 : データの消費者。使用するリスト (データが存在する場合) の先頭をポップします。また、他のスレッドがデータをプッシュできるように、SLOT も利用できます。このリストに直接アクセスできるオブジェクトは、元の QObject クラスだけです。

オブジェクト 2 : データのプロデューサー。リストにデータをプッシュします。他の人がデータを「ping」するために利用できるSLOTSがあり、リストからデータをポップするSIGNALを発行します。他のオブジェクトは、このリストに直接アクセスできません。

Obj 3: obj 1 のデータを生成し、obj 2 からデータを消費します。obj 1 に送信されたデータと obj 2 からのデータを追跡する独自の内部データ構造を持っていますQwtPlots。何らかの分析を行います。

Obj の 1 と 2 はリアルタイム クリティカルであり、QueryPerformanceCounter スタイルの「タイミング」を使用します。これにより、実行中にそれぞれ CPU が消費されます。すべてのループを実行QCoreApplication::processEvents()して、発生するイベントを処理します。

これはクロススレッド データ共有を処理する適切な方法ですか? そうでない場合、穴はどこにあり、どのように修正しますか? これにより、飛び回るデータの「コピー」が大量に作成されることは理解していますが、現時点ではメモリの膨張は問題ではありません。

前もって感謝します :)

4

1 に答える 1

2

スレッドを使用するとうまくいかないことがたくさんあるので、すべての実装の詳細がなければ、スレッドセーフかどうかを正確に言うのは困難です。

Obj 1 : データの消費者。使用するリスト (データが存在する場合) の先頭をポップします。また、他のスレッドがデータをプッシュできるように、SLOT も利用できます。このリストに直接アクセスできるオブジェクトは、元の QObject クラスだけです。

このスロットがキューまたは自動接続タイプを使用して他のスレッド (Obj 3 など) のシグナルに接続されている場合、Obj 1 はおそらく安全です。スロットが他のスレッドから直接呼び出された場合、すべてを明示的に同期しない限り、明らかにスレッドセーフではありません。

オブジェクト 2 : データのプロデューサー。リストにデータをプッシュします。他の人がデータを「ping」するために利用できるSLOTSがあり、リストからデータをポップするSIGNALを発行します。他のオブジェクトは、このリストに直接アクセスできません。

「ping」がどのように実装されているか、またはどのスレッドがそれらのスロットを呼び出すかについては言及していません。他のスレッドがそれらを直接呼び出し、ping に内部 std::list へのアクセスが含まれる場合、問題が発生します。それらのスロットがキュー接続または自動接続を介してのみ呼び出される場合 (たとえば、Obj 3 のシグナルに対して)、問題ありません。それらのスロットがスレッド セーフである場合 (たとえば、"ping" メッセージをある種の内部同期メッセージ キューに入れるだけである場合)、それも問題ありません。ただし、後者の方法は、キュー接続メカニズムのカスタム再実装のように見えます。

全体として、スロットはどこからでも誤って呼び出される可能性があるため、この全体は私には危険すぎるように見えます。次のように、いくつかの安全チェックを配置することで、この種のことを回避しようとします。

void Obj2::ping() {
    if (QThread::currentThread() != this->thread()) {
        // not sure how efficient it is
        QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
        return;
    }
    // thread unsafe code goes here
}
于 2011-09-28T18:30:45.530 に答える