2012-04-05 4 views
1

InstanceContextMode = SingleおよびConcurrencyMode = Multipleでタグ付けされた単純なWCFサービスがあります。リストを返すメソッドでは、データベースにアクセスして呼び出しが行われたときにリストを埋めるのではなく、単にリストのローカルコピーを返します。リストはバックグラウンドスレッドによって維持され、バックグラウンドスレッドは24時間ごとにデータベースにアクセスし、リストを再投入します。オブジェクトを2つの場所にロックすることで、並行処理の問題を処理します。コレクションを返すメソッドの内部と、コレクションを満たすメソッドの内部です。マルチスレッドWCFサービスにおける効率的なコレクションのメンテナンス

私の質問は、これをより効率的にする方法です。現在、私たちは、クライアントが呼び出すことをサービスメソッド「GetCustomers」のボトルネックを持っています。

public List<ZGpCustomer> GetCustomers() 
{ 
    List<ZGpCustomer> customerListCopy = new List<ZGpCustomer>(); 
    lock (_customerLock) 
    { 
     customerListCopy = new List<ZGpCustomer>(_customers); 
    } 

    return customerListCopy; 
} 

「_customersは」唯一の24時間ごとに充填されているので、我々は唯一のすべての内部でロックする必要があるのと同様に、それはそうコレクションを変更するときにのみGetCustomersメソッドを使用します。現在設定されている方法では、1000回のリクエストが同時に入力されると、一度に1つのスレッドだけがそのメソッドにアクセスできるため、1000リクエストを効果的にキューイングします。これは、サービスのマルチスレッドの側面をいくらか無駄にしています。

このようなパターンにはベストプラクティスがありますか?オブジェクトを格納するために、より適切なデータコレクションを使用する必要がありますか? "BlockingCollection"はより適切なフィットになりますか?

+0

library/system.collections.concurrent.aspx – mattanja

答えて

2

これを行うためのより効率的な方法が最も確実です。そのトリックは、コレクションへのマスター参照を不変に保つことです。そうすれば、読者側でアクセスを同期させる必要はありません。ライター側だけがロックを必要とします。読者側には何も必要ありません。これは、読者が非常に並行しているということです。あなたがする必要があるのは、_customersの参照をvolatileとしてマークすることだけです。

// Variable declaration 
object lockobj = new object(); 
volatile List<ZGpCustomer> _customers = new List<ZGpCustomer>(); 

// Writer 
lock (lockobj) 
{ 
    // Create a temporary copy. 
    var copy = new List<ZGpCustomer>(_customers); 

    // Modify the copy here. 
    copy.Add(whatever); 
    copy.Remove(whatever); 

    // Now swap out the references. 
    _customers = copy; 
} 

// Reader 
public List<ZGpCustomer> GetCustomers() 
{ 
    return new List<ZGpCustomer>(_customers); 
} 

あなたは少しあなたが_customersの不変性を悪用する可能性がありGetCustomersの署名を変更して、読み取り専用ラッパーを返すために喜んでいる場合。あなたは、私が速くロック以外のものを処理する推測System.Collections.Concurrent内のコレクションを見て可能性:http://msdn.microsoft.com/de-de/任意の証拠なし

// Reader 
public IList<ZGpCustomer> GetCustomers() 
{ 
    return _customers.AsReadOnly(); 
} 
+0

お返事ありがとうございます...顧客リストの読み取り専用のコピーを返すという2番目のコメントについてもう少し説明してください。 readonlyのコピーに関するあなたの提案に従うのではなく、実行するリスクは何ですか? – Thelonias

+1

パフォーマンスをさらに向上させる 'GetCustomers'では実際のコピー操作が必要ないかもしれないという点を、* copy *の代わりに* wrapper *と言っておきましょう。 –

+0

ああ、やったよ。情報にもう一度感謝します。私は揮発性の価値を大いに見たことがないので、時間だと思います! – Thelonias

関連する問題