0

から派生したいくつかのクライアント GUI ウィンドウがありますQMainWindow。各ウィンドウは異なるタスクを実行している可能性がありますが、すべてが として実装された中央キャッシュからデータを要求していQThreadます。

すべてのクライアントslotがデータ キャッシュ内の同じものに接続し、 signals を発行して、データ キャッシュに何かを実行するように促します。データ キャッシュへのsignals はキューに入れられるため、データ キャッシュは一度に 1 つのことしか実行しません。

データ キャッシュが完了すると、実行していた処理が完了したことを正しいクライアントに通知する必要があります。私の当面の考えはsignal、完了について要求しているクライアントに a を送信することです。これは、特定のクライアントに接続してから、それに を送信することを意味しslotますsignal

クライアントに接続してから切断する必要がありますか? QObject::sender()仕入先を取得する機能は承知しています。その送信者 (クライアント) のみに信号を発信する方法はありますか? または、これを行う他の方法はありますか?

4

1 に答える 1

0

問題を解決するためのより簡単な方法があるかもしれません。たとえば、QtConcurrentフレームワークを調べることを検討します。または、キャッシュに何かを要求する前に、クライアントが最初にキャッシュの「終了」シグナルに接続するように、設計を再構築することもできます。そのすべてに失敗した場合は、 QMetaObject::invokeMethod関数 (クライアントまたはキャッシュのいずれか) に依存することを検討することもできます。この関数を使用すると、(スレッドセーフな方法で) 任意のジェネリック引数を使用して、任意の QObject (それへのポインターがある場合) で任意のメソッドを呼び出すことができます。

このアプローチを使用する場合QMetaObject::invokeMethod、いくつかの欠点に注意する必要があります。まず、文字列名を使用してメソッドを呼び出す必要があります。つまり、間違った名前を使用しているかどうかがコンパイル時にわかりません。第二に、クライアントは中央キャッシュとは異なるスレッド アフィニティを持っているため、キャッシュがそれらのメソッドを呼び出したときにクライアントが破棄される可能性があります (ただし、おそらくあなたの場合、これは問題にはなりません)。 . 最後に、クライアントで実行する必要があるメソッドの名前をキャッシュに認識させたくない場合があります。

最初の欠点を回避する方法はありません (今後の Qt 5.0 リリースでこれが異なる方法で処理されるかどうかはわかりません)。2 番目と 3 番目の問題に関しては、メソッドへの参照をカプセル化するオブジェクトを作成することをお勧めします。次のようなものです。

class MethodReference
{
   MethodReference(QObject* object, const QString& methodName);

   ...

   bool invoke(QGenericArgument val0 = QGenericArgument(),
               QGenericArgument val1 = QGenericArgument(),
               ...
               QGenericArgument val9 = QGenericArgument());

private:
   QPointer<QObject> mObject;
   QString mMethod;
};

次に、このオブジェクトをクライアントからキャッシュに渡します。次に、キャッシュはこのオブジェクトで invoke を呼び出します。

--の使用に注意してください。QPointerこれにより、メソッドを呼び出す前に、オブジェクトが破棄されているかどうかをスレッドセーフに確認できます。以前にこれを行ったので、Qt の 4.8 より前のバージョンには、マルチスレッド コンテキストでクラッシュを引き起こすバグがQPointerあったこともお知らせします。これを行う場合は、より新しいバージョンの Qt を使用してください。

これが明確だったことを願っています。

于 2012-08-17T22:02:36.747 に答える