4

値がリストexにエクスポートされ、その辞書がクリアされた状態でConcurrentDictionaryスレッドセーフを作成するアイデア。そのため、他のスレッドはエクスポートとクリアの間にデータを追加できません。このようConcurrentDictionaryとClear() - 関数です。データ損失なしで値をスレッドセーフにエクスポートする

: は「

List<data> list; 
list = (List<data>)_changedItems.Values; //get values before clearing 
_changedItems.Clear(); 

」 そして追加が機能_changedItems.AddOrUpdate

で他のスレッドによって行われている今、辞書から抜け出すのデータの間に新たなデータを失う可能性があるとあるスレッドがクリアの行の前にコレクションにデータオブジェクトを追加すると、コンテンツをクリアします。

また、内部ロックの追加とクリアを行う唯一の方法です。

lock(object) 
{ 
    List<data> list; 
    list = (List<data>)_changedItems.Values; 
    _changedItems.Clear(); 
} 

そして

lock(object) 
    _changedItems.AddOrUpdate 

2スレッドを呼び出して、実際に

-Larry

+1

辞書インスタンスをローカルに割り当てる、空の別の辞書を作成する、ロックする、インスタンスを上書きする、ロックを解除する、古いものを返す、すべてのスレッドが同じ参照を使用する場合にのみ動作します。値によってコピーがある場合、これは機能しません。 –

+0

別の考え方 - これを行うことができれば、Interlocked.Exchangeを使用してインスタンスをスワップして、ロックを解除することができます。ロックを短くしたり削除したりすることは、パフォーマンス(そしてデッドロック回避、おそらくここでは関係ありませんが)には常に良いニュースです。 –

答えて

2

..安全に辞書からすべてクリアアイテムを返すクリア機能の必要性がありますシーケンス内の安全なメソッドは、シーケンス自体のアトミック性を保証しません。あなたは値とクリアを取得するために両方の呼び出しにlockが必要であることは間違いありません。

0

TryRemove(key, out value)メソッドを使用できます。削除された要素を返します。この方法では、バッファされたデータを移動するために辞書をロックする必要はありません。

List<data> list; 
var keys = dict.Keys; 
foreach(var key in keys) 
{ 
    data value; 
    dict.TryRemove(key, out value); 
    list.Add(value); 
} 

更新:実際には、それが変化している間もConcurrentDictionaryの真上に繰り返すことができます。この方法では、実装によっては、遅いかもしれないプロパティ.Keysからキーのコレクションを構築する必要はありません。

List<data> list; 
foreach(var kvp in dict) 
{ 
    data value; 
    dict.TryRemove(kvp.Key, out value); 
    list.Add(value); 
} 
関連する問題