1

デジタル信号取得システムでは、多くの場合、データは1つのスレッドによってシステム内のオブザーバーにプッシュされます。

Wikipedia / Observer_patternの例:

foreach (IObserver observer in observers)
    observer.Update(message);

たとえば、GUIスレッドからのユーザーアクションでデータの流れを停止する必要がある場合は、サブジェクトとオブザーバーの接続を切断し、オブザーバーをまとめて破棄する必要があります。

議論の余地があるかもしれません。データソースを停止し、番兵の値が接続を破棄するのを待つ必要があります。ただし、システムの遅延が大きくなります。

もちろん、データポンピングスレッドがオブザーバーのアドレスを要求したばかりの場合は、破壊されたオブジェクトにメッセージを送信していることに気付く可能性があります。

誰かがこの状況に対抗する「公式の」デザインパターンを作成しましたか?彼らはすべきではありませんか?

4

2 に答える 2

2

データ ソースを常に同時実行の安全な側に置きたい場合は、常に安全に使用できるポインターを少なくとも 1 つ用意する必要があります。したがって、Observer オブジェクトの有効期間は、データ ソースの有効期限より前に終了しない必要があります。

これは、オブザーバーを追加するだけで実行できますが、削除することはありません。各オブザーバーにコア実装自体を実行させるのではなく、このタスクを ObserverImpl オブジェクトに委譲させることができます。この impl オブジェクトへのアクセスをロックします。これは大したことではありません。オブザーバーが ObserverImpl オブジェクトを使用してビジーな場合に備えて、GUI アンサブスクライバーがしばらくの間ブロックされることを意味します。GUI の応答性が問題になる場合は、サブスクリプション解除ジョブがプッシュされた、ある種の同時ジョブ キュー メカニズムを使用できます。(Windows の PostMessage のように)

サブスクライブを解除するときは、コア実装をダミー実装に置き換えるだけです。繰り返しますが、この操作はロックを取得する必要があります。これは確かにデータ ソースの待機を発生させますが、これは単なる [ロック - ポインター スワップ - ロック解除] であるため、リアルタイム アプリケーションには十分高速であると言えます。

ダミーのみを含む Observer オブジェクトをスタックするのを避けたい場合は、何らかの簿記を行う必要がありますが、これはリストから必要な Observer オブジェクトへのポインターを保持するオブジェクトのような些細なことに要約される可能性があります。

最適化 : Observer 自体が実行されている限り、実装 (実際の実装 + ダミー) も維持する場合は、実際のロックなしでこれを実行し、InterlockedExchangePointer などを使用してポインターを交換できます。最悪のシナリオ: ポインターがスワップされている間に委任呼び出しが行われている --> 大したことはなく、すべてのオブジェクトが存続し、委任を続行できます。次の委譲呼び出しは、新しい実装オブジェクトに対して行われます。(もちろん、新しいスワップを除いて)

于 2008-09-19T15:37:01.060 に答える
0

すべてのオブザーバーにメッセージを送信して、データソースが終了していることを通知し、オブザーバーにリストから自分自身を削除させることができます。

コメントに応じて、サブジェクト-オブザーバーパターンの実装により、オブザーバーの動的な追加/削除が可能になるはずです。event += observerC#では、イベントシステムは、オブザーバーがを使用して追加され、を使用して削除されるサブジェクト/オブザーバーパターンevent -= observerです。

于 2008-09-17T11:18:56.603 に答える