私はプログラムを書いています、それはで画像を表示するはずQLabel
ですQWidget
。画像はサーバーから送信されます。まず、サーバーからの接続とデータの受信を担当するスレッドがあります。データを受信すると、ソケットスレッドはスロットgotNewData(Imagedata)
に接続された信号を送信します。QWidget
updateImage(Imagedata)
スロットで、updateImage(Imagedata)
サーバーから取得した画像データをに変換し、画像をQImage
拡大縮小して作成しQPixmap
、に設定しQLabel
ます。私の問題は、処理updateImage(Imagedata)
機能中に、ソケットが新しい画像を含む他のパッケージを取得し、信号をQWidget
何度も送信することです。ソケットスレッドは関数がかどうかを気にしないので、それは論理的ですupdateImage(Imagedata)
、前のシグナル呼び出しによって呼び出されたが、すでに終了しているかどうか。QWidget
updateImage(Imagedata)
私の質問は:ソケットスレッドを関数と同期させる方法はありますか?
1 に答える
間違いなくあります。問題は、古い画像がまだ処理されている間に新しい画像を受信した場合に、正確に何を達成したいのかということです。新しいものをスキップして最後まで古いものを処理したい場合は、オブジェクトの送信時に blockSignals を呼び出すことをお勧めします。これにより、呼び出し元と呼び出し元のスピアレーションが破壊されますが、qt はシグナルの受信をブロックすることを許可していないようで、送信するだけです。パフォーマンスにあまり影響を与えず、他の通信ネットワークスレッドを混乱させない変更は、ラベルを含むウィジェットでプロキシ QObject を作成し、moveToThread() を使用してそれをネットワークスレッドに移動し、これで blockSignals を使用することです。物体。当然、このオブジェクトは、実際に送信される信号と同じ署名の信号を必要とします。作成されたオブジェクトは、スレッド アフィニティが異なりますが、論理的には GUI ウィジェットによって所有されたままになります。
もう 1 つの方法は、オブジェクトに bool 変数を作成processing
し、データを処理している場合は true に設定することです。false に戻す直前にQCoreApplication::processEvents();
、イベント キュー内のすべてのイベントを処理する呼び出しを行います。スロットでprocessing
vaiable が設定されているかどうかを確認し、設定されている場合はスキップする必要があります。シンプルで粗野な魂ですが、うまくいきます。processEvents();
GUI スレッドで他のイベント ハンドラーを呼び出している場合 (たとえば、そのような複数のラベル)、一部のラベルはデータの取得をまったく停止 (フリーズ) する可能性があることに注意してください。
処理が完了する前に、ネットワーク スレッドが何も受信しないようにするために使用したくなるかもしれませんがQt::BlockingQueuedConnection
、それはさまざまな理由から悪い考えです (そのように同期する場合、なぜ別のスレッドが必要なのですか?)