1

次のコードがあります。

    var sequence = from row in CicApplication.DistributorBackpressure44Cache
                   where row.Coater == this.Coater && row.IsDistributorInUse
                   select new GenericValue
                   {
                       ReadTime = row.CoaterTime.Value,
                       Value = row.BackpressureLeft
                   };

    this.EvaluateBackpressure(sequence, "BackpressureLeftTarget");

また、DistributorBackpressure44Cache は次のように定義されています。

internal static List<DistributorBackpressure44> DistributorBackpressure44Cache
{
    get
    {
        return _distributorBackpressure44;
    }
}

これは、DistributorBackpressure44Cache を 1 つのスレッドで更新し、上記のように別のスレッドからクエリを実行できる、高度にスレッド化されたアプリケーションの一部です。上記の変数 'sequence' は IEnumerable であり、示されているメソッドに渡され、実際に実行される前に他のメソッドに渡される可能性があります。私の懸念はこれです。クエリが実際に実行されたときに DistributorBackpressure44Cache が更新されている (クリアされて再設定されている) 場合、上記のクエリはどうなりますか?

このクエリは実際には後で実行されるため (すぐにリストに変換しない限り)、このコードをロックしても意味がありません。

4

3 に答える 3

1

すぐにリストに変換できます(ベストかもしれません--)

また

キャッシュ リフレッシュ ロックと同期する DistributorBackpressure44 の get にロックを設定できます。ロックされたアクセサーとロックされていないアクセサーを含めることができます。結果がすぐに使用される場合はロックされていないアクセサーを使用し、遅延実行状況でアクセサーが使用される場合はロックされたアクセサーを使用します。

キャッシュの更新によってリスト _distributorBackpress44 が変更された場合でも、参照されたリストが置き換えられた場合にのみ機能しないことに注意してください。

于 2012-11-29T17:38:49.040 に答える
1

設計が許容できる場合は、このコードを使用してスナップショット レベルの分離を確保し、ロックを完全に回避できます。ただし、次のことを行う必要があります。

  1. 代わりにreturn DistributorBackpressure44CacheaReadOnlyCollection<T>を作成します。このようにして、このデータを変更してはならないことが明示されます。

  2. _distributorBackpressure44変更がコピーで発生し、_distributorBackpressure44完了時にアトミックな割り当てが返されることを確認してください。

    var cache = _distributorBackpressure44.ToList();
    this.RefreshCache(cache); // this assumes you *need* to know 
                              // about the structure of the old list
                              // a design where this is not required
                              // is preferred
    
    _distributorBackpressure44 = cache; // some readers will have "old"
                                        // views of the cache, but all readers
                                        // from some time T (where T < Twrite)
                                        // will use the same "snapshot"
    
于 2012-11-29T17:39:27.367 に答える
0

アーキテクチャ オプションについて詳しく知らなくても、次のようなことができます。

lock(CicApplication.DistributorBackpressure44Cache)
{
    var sequence = from row in CicApplication.DistributorBackpressure44Cache
                   where row.Coater == this.Coater && row.IsDistributorInUse
                   select new GenericValue
                   {
                       ReadTime = row.CoaterTime.Value,
                       Value = row.BackpressureLeft
                   };
}

this.EvaluateBackpressure(sequence, "BackpressureLeftTarget");

次に、クリア/更新を行うコードでは、次のようなものになります。

lock(CicApplication.DistributorBackpressure44Cache)
{
    var objCache = CicApplication.DistributorBackpressure44Cache

    objCache.Clear();

    // code to add back items here
    // [...]
}

キャッシュを取り巻くすべてを制御する中央クラス (Singleton パターンでしょうか?) を持つ方がクリーンです。しかし、これがどれほど実現可能かはわかりません (つまり、クエリ コードを別のクラスに入れ、パラメーターを渡します)。手の込んだものの代わりに、このオブジェクトに対して読み取り/書き込みを行うたびに常に lock() を一貫して覚えている限り、上記のソリューションは機能するはずです。

于 2012-11-29T17:37:02.860 に答える