답변:
짧은 대답 : 쉬운 방법으로는 할 수 없습니다.
ConcurrentBag는 각 스레드에 대한 스레드 로컬 큐를 유지하며 자신의 큐가 비워지면 다른 스레드의 큐만 확인합니다. 항목을 제거했다가 다시 넣으면 제거하는 다음 항목이 다시 동일한 항목이 될 수 있습니다. 항목을 반복적으로 제거했다가 다시 넣으면 모든 항목을 반복 할 수 있다는 보장은 없습니다.
두 가지 대안 :
당신은 할 수 없습니다. 가방인데 주문되지 않았습니다. 다시 넣으면 끝없는 루프에 갇히게 될 것입니다.
당신은 세트를 원합니다. ConcurrentDictionary로 하나를 에뮬레이션 할 수 있습니다. 또는 잠금으로 자신을 보호하는 HashSet.
HashSet그가 설명 하는 대로 a 를 "에뮬레이트"할 것 입니다.
ConcurrentBag는 항목을 추가하고 여러 스레드에서 열거 할 수있는 목록을 처리하는 데 유용하며 이름이 제안하는대로 결국 버릴 수 있습니다. :)
Mark Byers가 말했듯 이 제거하려는 항목을 포함하지 않는 새 ConcurrentBag를 다시 빌드 할 수 있지만 잠금을 사용하여 여러 스레드 히트로부터이를 보호해야합니다. 이것은 한 줄짜리입니다.
myBag = new ConcurrentBag<Entry>(myBag.Except(new[] { removedEntry }));
이것은 작동하며 ConcurrentBag가 설계된 정신과 일치합니다.
Mark는 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);
}
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찾을 때까지 반복합니다 . 코드 전용 답변은 권장하지 않으므로 솔루션을 설명해야합니다. itembag
이것은 내 프로젝트에서 사용중인 확장 클래스입니다. 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;
}