回答:
簡単に言えば、簡単な方法でそれを行うことはできません。
ConcurrentBagは各スレッドのスレッドローカルキューを保持し、独自のキューが空になると、他のスレッドのキューのみを調べます。アイテムを削除して元に戻すと、次に削除するアイテムは同じアイテムになる可能性があります。アイテムを繰り返し削除して元に戻すと、すべてのアイテムを繰り返し処理できるという保証はありません。
あなたのための2つの選択肢:
できません。そのバッグ、それは注文されていません。元に戻すと、無限ループに陥るだけです。
あなたはセットが欲しい。ConcurrentDictionaryでエミュレートできます。または、ロックで身を守るHashSet。
HashSet彼が説明するように、それはa を「エミュレート」します。
ConcurrentBagは、アイテムを追加して多くのスレッドから列挙できるリストを処理し、その名前が示唆しているように最終的にそれを破棄するのに最適です:)
Mark Byersが言ったように、削除したいアイテムを含まない新しいConcurrentBagを再構築できますが、ロックを使用してこれを複数のスレッドヒットから保護する必要があります。これはワンライナーです:
myBag = new ConcurrentBag<Entry>(myBag.Except(new[] { removedEntry }));
これは機能し、ConcurrentBagが設計された精神と一致します。
マークは、ConcurrentDictionaryがあなたが望む方法で機能するという点で正しいです。引き続きConcurrentBagを使用したい場合は、効率的ではない次の方法でアクセスできます。
var stringToMatch = "test";
var temp = new List<string>();
var x = new ConcurrentBag<string>();
for (int i = 0; i < 10; i++)
{
x.Add(string.Format("adding{0}", i));
}
string y;
while (!x.IsEmpty)
{
x.TryTake(out y);
if(string.Equals(y, stringToMatch, StringComparison.CurrentCultureIgnoreCase))
{
break;
}
temp.Add(y);
}
foreach (var item in temp)
{
x.Add(item);
}
あなたが言うように、それTryTake()が唯一の選択肢です。これは、MSDNの例でもあります。Reflectorには、他に興味のある隠された内部メソッドもありません。
public static void Remove<T>(this ConcurrentBag<T> bag, T item)
{
while (bag.Count > 0)
{
T result;
bag.TryTake(out result);
if (result.Equals(item))
{
break;
}
bag.Add(result);
}
}
ConcurrentBagは順不同のコレクションですが、コードはそれbag.TryTakeを期待bag.Addし、FIFOの方法で機能します。コードはがをbag含むと想定しitem、で見つかるまでループitemしbagます。コードのみの回答はお勧めしません。解決策を説明する必要があります。
これは私のプロジェクトで使用している拡張クラスです。ConcurrentBagから単一のアイテムを削除でき、バッグからアイテムのリストを削除することもできます
public static class ConcurrentBag
{
static Object locker = new object();
public static void Clear<T>(this ConcurrentBag<T> bag)
{
bag = new ConcurrentBag<T>();
}
public static void Remove<T>(this ConcurrentBag<T> bag, List<T> itemlist)
{
try
{
lock (locker)
{
List<T> removelist = bag.ToList();
Parallel.ForEach(itemlist, currentitem => {
removelist.Remove(currentitem);
});
bag = new ConcurrentBag<T>();
Parallel.ForEach(removelist, currentitem =>
{
bag.Add(currentitem);
});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
public static void Remove<T>(this ConcurrentBag<T> bag, T removeitem)
{
try
{
lock (locker)
{
List<T> removelist = bag.ToList();
removelist.Remove(removeitem);
bag = new ConcurrentBag<T>();
Parallel.ForEach(removelist, currentitem =>
{
bag.Add(currentitem);
});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
public static ConcurrentBag<String> RemoveItemFromConcurrentBag(ConcurrentBag<String> Array, String Item)
{
var Temp=new ConcurrentBag<String>();
Parallel.ForEach(Array, Line =>
{
if (Line != Item) Temp.Add(Line);
});
return Temp;
}
どうですか:
bag.Where(x => x == item).Take(1);
それはうまくいきます、私はどれほど効率的かわかりません...