C#에서는 여러 스레드를 이용하여 동시에 다루어야 하는 objects group을 위한 class가 여러개 있는데, 그 중 하나가 ConcurrentBag<T>이다.
ConcurrentBag으로부터 elements 추가, 접근, 삭제를 하는 방법을 알아보자. 그리고, ConcurrentBag<T>의 장단점도 정리해보자.
What Is a ConcurrentBag in C#?
generic collection type이다.
namespace : System.Collection.Generic
objects의 정렬되지 않은 collection이다. (ConcurrentBag에 items을 추가한 순서와, 되찾을떄의 순서가 같지 않다. indexer로 ConcurrentBag의 items에 접근할 수 없다. )
IProducerConsumerCollection<T> interface를 구현한다.
thread-safe collection이다.
How to Create a ConcurrentBag in C#
Creating an Empty ConcurrentBag in C#
ConcurrentBag<int> myNumbers = new();
Creating a ConcurrentBag With Initial Items
var myConcurrentBag = new ConcurrentBag<int>() { 2, 4, 6, 8, 10 };
ConcurrentBag은 지정된 용량없이, 수행하는 동작에 따라 사이즈가 증가/감소할 수 있다.
Creating a ConcurrentBag by Passing Another Collection as an Argument
var myList = new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
var myConcurrentBag = new ConcurrentBag<int>(myList);
datatype만 동일하다면 IEnumerable<T>를 전달하여 ConcurrentBag<T>를 생성할 수 있다.
Working With a ConcurrentBag in a Multithreaded Environment
ConcurrentBag<T>를 사용하여 멀티스레드 환경에서 안전하게 데이터를 처리해보자.
Adding Elements to a ConcurrentBag Concurrently
public static ConcurrentBag<int> CreateAndAddToConcurrentBagConcurrently()
{
ConcurrentBag<int> numbersBag = new();
Parallel.For(0, 1000, i =>
{
numbersBag.Add(i);
});
return numbersBag;
}
Paraller.For method로 병렬로 loop를 실행할 수 있다.
Remove Elements From a ConcurrentBag Concurrently
public static ArrayList RemoveFromConcurrentBagConcurrently(ConcurrentBag<int> bag)
{
var numbersList = new ArrayList();
Parallel.For(0, 20, i =>
{
if (bag.TryTake(out int number))
{
Console.WriteLine($"Thread {Environment.CurrentManagedThreadId} took item: {number}");
numbersList.Add(number);
}
});
return numbersList;
}
TryTake 함수는 ConcurrentBag<T> class 함수이다.
동시다발성 동작이므로, ConcurrentBag으로부터 item이 삭제되는 순서와 console print 순서는 다르다.
Access an Element in a ConcurrentBag Concurrently
TryPeek 함수를 사용한다. 삭제없이 ConcurrentBag으로부터 object를 반환한다.
public static void AccessItemFromAConcurrentBagConcurrently(ConcurrentBag<int> bag)
{
Parallel.For(0, 50, i =>
{
if (bag.TryPeek(out int number))
{
Console.WriteLine("Thread {0} peeked item: {1}", Environment.CurrentManagedThreadId, number);
}
});
}
ConcurrentBag Class의 다른 함수들
ToArray
ConcurrentBag의 모든 elements를 new array에 복사한다.
public static int[] ConcurrentBagToArrayMethod(ConcurrentBag<int> bag)
{
var myArray = new int[bag.Count];
myArray = bag.ToArray();
return myArray;
}
CopyTo
존재하는 1차원 배열에 지정된 index부터 복붙한다.
public static int[] ConcurrentBagCopyToMethod(ConcurrentBag<int> bag)
{
var someArray = new int[bag.Count];
bag.CopyTo(someArray, 0);
return someArray;
}
Clear
ConcurrentBag의 모든 items을 삭제하는 thread-safe 함수이다.
언제 ConcurrentBag을 사용하는가?
멀티스레드에서 동시에 collection items를 조작하고, 순서는 상관 없을때 사용한다.
순서를 고려해야 한다면 ConcurrentQueue 또는 ConcurrentStack을 사용해야 한다.
장점
thread safety를 제공한다. lock-free mechanism을 사용하여 프로그램 퍼포먼스를 향상시킨다.
비정렬하므로 동적으로 사이트를 조절할 수 있다.
단점
순서가 중요할때는 사용할 수 없다.
결론
ConcurrentBag은 멀티스레드에서 items를 저장 회수하기 유용하지만, 순서가 보장되지 않는다. 필요에 따라 알맞는 collection을 선택할 수 있다.
'C#' 카테고리의 다른 글
.NET] DTO vs POCO 차이점 (0) | 2023.02.09 |
---|---|
C#] System.Security.Cryptography (0) | 2023.01.16 |
C#] IEnumerable vs Enumerable 차이점 (0) | 2023.01.09 |
구성관리자] 조건부 컴파일 기호, connectionStrings 관리 (0) | 2022.12.14 |
C#] MSSQL AES128/256, SHA256 암복호화 어셈블리 DLL 만들기 (0) | 2022.12.09 |
댓글