6

値がリスト ex にエクスポートされ、その辞書がクリアされた後に ConcurrentDictionary をスレッドセーフにするアイデア。エクスポートとクリアの間に他のスレッドがデータを追加できないようにします。

このような: "

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

ディクショナリからクリアされたすべてのアイテムを安全に返す Clear 関数が必要です。

-ラリー

4

2 に答える 2

2

実際、シーケンス内で 2 つのスレッドセーフなメソッドを呼び出しても、シーケンス自体の原子性は保証されません。lock値を取得するための呼び出しとクリアするための両方の呼び出しが必要であることは正しいです。

于 2012-01-24T13:14:54.490 に答える
2

メソッドを使用できます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);
}
于 2012-04-24T17:14:15.957 に答える