0

私は現在、いくつかの部分で構成されるシステムを (再) 設計しています:

  • 最初の部分は、ソースからフレームを (非同期的に) 取得し、フレームの準備が整うたびに Qt シグナルを介してイベントを発生させるエンティティです。
  • 2 番目の部分は、フレームをリアルタイムで表示する GUI であり、スロットによって上記の信号に接続されています。
  • 最後の部分は、GUI からの数種類の信号に応答する可能性のあるシーケンシャル アルゴリズム (while、for など) によって動作が最もよく記述されるフレーム プロセッサです。

主な質問は、そのようなコードを整理するためのベスト プラクティスがあるかどうかです。

私が思いつき、あまり好きではない解決策は、4つのスレッドを実行することです。

  • Qt シグナルを介して他の 3 つのスレッドと通信する GUI スレッド
  • フレームが利用可能になるたびにシグナルを送信するフレーム ソース スレッド。
  • シグナル時にフレームを格納し、QWaitCondition を使用してフレーム プロセッサ スレッドに通知するフレーム オーガナイザー スレッド。
  • フレーム オーガナイザから getNextFrame() を呼び出すフレーム プロセッサ スレッド。

しかし、おそらく異なるパラダイム(待機条件とシグナル)が混在しているため、これは良い解決策ではないと思います。さらに、条件付きで待機すると、イベント処理キューが枯渇する可能性があります。

4

1 に答える 1

1

を使用する必要はありませんQWaitCondition。スレッドはベア (非派生) である必要がありますQThreads。その中にすべてのコードを入れて、QObjectsそれらのスレッドに移動します。フレーム オーガナイザは、フレーム プロセッサに信号を送信するだけです。シグナルは、スレッドのイベント ループにイベントを投稿することによって、スレッドの境界を越えて配信されます。これらのイベント ループは内部的に同期プリミティブ (ミューテックス) を使用してアクセスをシリアル化するため、車輪を再発明する必要はありません。QThread のデフォルトの実装はrun()単にイベント ループをスピンするだけなので、スレッドをインスタンス化して開始する以外に何もする必要はありません。

GUIスレッドでインスタンス化されたすべてのQObjectを使用して、おそらくパフォーマンスが低下してコードが実行されるはずです。それらを別のスレッドに移動することは、ベンチマークでどのオブジェクトが CPU バウンドであるかが示されている場合に行われます。このルールには、残念ながら必要な例外があります。カメラ コードが、カメラ ドライバーによって提供されるブロッキング API (何かを非同期的に報告する代わりに待機する API) しか使用できない場合、そのためにスレッドを犠牲にするしかありません。 . このような専用のブロッキング回避スレッドを除いて、アプリケーションは、使用可能なコアとほぼ同じ数のスレッドを合計で使用する必要があります (QThread::idealThreadCount())。その数までのスレッドをインスタンス化し、これらのスレッド間で QObject をランダムまたはラウンドロビン方式で配布します。繰り返しますが、CPU バウンドの QObject のみを移動してください。ノンブロッキング API (ネットワーキング!) を使用する IO バウンド オブジェクトは、その処理を必要としません。正常なデバイス ドライバー ( http://www.ftdichip.com/のようなもの) は、によってシグナルに変換できる非同期イベント通知を公開しますQWinEventNotifier。これは Qt 4.x のプライベート API ですが、それでも問題なく動作します。

多くの一般的な API がブロックされていることは、本当に嘆かわしいことです。データベース ドライバはその典型的な例です。QTcpSocketたとえば、データベースがそれを使用するスレッドをブロックしないように、mysqlクライアントドライバーを使用するように移植しました。

于 2012-07-01T15:27:16.753 に答える