programing

목록 대신 Blocking Collection을 사용할 때와 Concurrent Bag을 사용할 때

newsource 2023. 4. 20. 21:30

목록 대신 Blocking Collection을 사용할 때와 Concurrent Bag을 사용할 때

"왜 병렬이 이루어지는가?"라는 질문에 대한 승인된 답변입니다.For Each code freeze up?」(각 코드 freeze up?)은 WPF 어플리케이션에서 List usage by ConcurrentBag로 대체하도록 권장합니다.

이 경우 Blocking Collection을 대신 사용할 수 있는지 알고 싶습니다.

이 은 쓸 수 .BlockingCollection하지만 그렇게 하는 것은 전혀 의미가 없다.

먼저 이 패키지는 를 구현하는 컬렉션의 래퍼입니다.이러한 인터페이스를 구현하는 모든 유형을 기본 스토리지로 사용할 수 있습니다.

를 작성하는 BlockingCollection<T>오브젝트에서는 제한 용량뿐만 아니라 사용할 컬렉션 유형도 지정할 수 있습니다.를 들어, 이렇게 하다를 할 수 .ConcurrentQueue<T> in, 동작 또는 in, first out(FIFO; First out) 동작을 ConcurrentStack<T> in,out( 동작의 객체. in, out(LIFO) 동작를 클래스는 모두 할 수 .IProducerConsumerCollection<T>인터페이스입니다.「」의 디폴트 은, 과 같습니다.BlockingCollection<T>ConcurrentQueue<T>.

여기에는 다음이 포함됩니다.ConcurrentBag<T>백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백.백 차단.백.백.백.백. IProducerConsumerCollection<T>단컬 ??『 』의 BlockingCollection내 것이 아니다) 라고 말한다 것이 아니다)

BlockingCollection<T>의 랩퍼로 사용됩니다.IProducerConsumerCollection<T>instance: 데이터를 삭제할 수 있을 때까지 컬렉션에서 삭제 시도를 차단할 수 있습니다.마찬가지로 a.BlockingCollection<T>에서 허가된 데이터 요소의 수에 상한을 적용하기 위해 작성할 수 있습니다.IProducerConsumerCollection<T> [...]

에서는 둘 할 가 없기 에 '도 할 가 없다'를합니다.BlockingCollection는 사용되지 않는 기능 계층을 추가합니다.

  • List<T>는 싱글 스레드애플리케이션에서 사용하도록 설계된 컬렉션입니다.

  • ConcurrentBag<T>입니다.Collections.Concurrent멀티스레드 환경에서 컬렉션 사용을 단순화할 수 있도록 설계된 네임스페이스입니다.Concurrent Collection을 사용하는 경우 다른 스레드에 의한 손상을 방지하기 위해 컬렉션을 잠글 필요가 없습니다.특별한 잠금 코드를 작성할 필요 없이 컬렉션에서 데이터를 삽입하거나 가져올 수 있습니다.

  • BlockingCollection<T>는 스레드 간의 공유 컬렉션에서 새로운 데이터를 사용할 수 있는지 여부를 확인할 필요가 없도록 설계되어 있습니다.공유 컬렉션에 새로운 데이터가 삽입되면 컨슈머 스레드가 즉시 활성화됩니다.따라서 일반적으로 while loop에서 특정 시간 간격으로 사용자 스레드에 새 데이터를 사용할 수 있는지 확인할 필요가 없습니다.

세이프가 할 List<T> 「」, 「」, 「」도 .ConcurrentBag<T> BlockingCollection<T>최선의 선택이 될 겁니다두 컬렉션은 모두 생산자와 소비자의 시나리오를 지원하기 위해 특화되어 있으므로 컬렉션에서 아이템을 동시에 추가 및 삭제하는 스레드가 여러 개 없는 한 다른 옵션을 찾아야 합니다(대부분의 경우 최적의 후보가 됩니다).

특히 에 대해서는 생산자와 소비자가 혼합된 시나리오를 대상으로 한 매우 전문적인 클래스입니다.즉, 각 worker-thread는 생산자이면서 소비자(같은 컬렉션에서 항목을 추가 및 삭제하는 것)가 될 것으로 예상됩니다.클래스의 내부 스토리지에 적합한 후보가 될 수 있지만, 그 외에는 이 클래스에 유리한 사용 시나리오를 상상하기 어렵습니다.

' 하다'라고 합니다.ConcurrentBag<T>입니다.List<T> 않다하지만 그렇지 않지.두 API의 유사성으로 인해 오해의 소지가 있습니다. " "Add a까지List<T>목록 끝에 항목을 추가할 때 결과가 표시됩니다.에의 콜ConcurrentBag<T>대신 가방 내 임의의 슬롯에 아이템을 추가할 수 있습니다.ConcurrentBag<T>기본적으로 순서가 없습니다.열거되도록 최적화되어 있지 않으며, 그렇게 하도록 명령받았을 때 작업이 제대로 수행되지 않습니다.내부적으로는 다수의 스레드 로컬 큐를 유지하므로 콘텐츠의 순서는 어떤 스레드가 언제 무슨 일이 일어났느냐가 아니라 어떤 스레드가 무엇을 했느냐에 따라 결정됩니다.의 각 열거 전에ConcurrentBag<T>이러한 스레드 로컬큐는 모두 어레이에 복사되어 가비지 콜렉터(소스 코드)에 압력이 가중됩니다.예를 들어, 이 선은var item = bag.First();하나의 요소만 반환하는 경우 전체 컬렉션의 복사본이 생성됩니다.

에 의해, 「」가 .ConcurrentBag<T>결과를 저장하기 위한 이상적인 선택은 아니다Parallel.For/Parallel.ForEachloopsyslog.syslog..syslog.

나은 스레드 List<T>.Add방법입니다."Enqueue"는 "Add"보다 덜 친숙한 단어이지만 실제로는 예상대로 작동합니다.

라고 하는 은 없다.ConcurrentBag<T> 수 있다ConcurrentQueue<T>예를 들어 둘 다 컬렉션에서 특정 항목을 제거하는 방법을 제공하지 않습니다.를 사용한 동시 컬렉션을 원하는 경우TryRemove가 있는 방법key파라미터를 지정하면 클래스를 볼 수 있습니다.

ConcurrentBag<T>는 마이크로소프트 문서의 태스크 병렬 라이브러리 관련 예제에 자주 나타납니다.를 들면 여기처럼요.누가 이 문서를 작성했든, 그들은 이 문서의 작은 사용 편의성 이점을 더 중요하게 여겼던 것 같습니다.Add대신Enqueue잘못된 수집을 사용했을 때의 동작/퍼포먼스상의 단점보다 큰 영향을 줍니다.이는 TPL이 처음 도입된 시기에 작성된 사례로, 병렬 프로그래밍에 익숙하지 않은 개발자들이 라이브러리를 신속하게 채택하는 것이 목표였다는 점을 고려하면 어느 정도 의미가 있습니다.난 알았어요,Enqueue처음 봤을 때 무서운 단어예요.안타깝게도 현재 모든 세대의 개발자들이 이 기술을 통합하고 있습니다.ConcurrentBag<T>이 컬렉션이 얼마나 특수한지 고려해 볼 때, 비록 그곳에 있는 것은 아니지만 그들의 정신적 도구에 있습니다.

루프의 결과를 소스 요소와 정확히 같은 순서로 수집하려면List<T>에 의해 lock대부분의 경우 오버헤드는 무시할 수 있습니다.특히 루프 내부의 작업이 엉성할 경우에는 더욱 그렇습니다.아래에 각 요소의 인덱스를 가져오는 LINQ 연산자의 예를 나타냅니다.

var indexedSource = source.Select((item, index) => (item, index));

List<TResult> results = new();

Parallel.ForEach(indexedSource, parallelOptions, entry =>
{
    var (item, index) = entry;
    TResult result = GetResult(item);
    lock (results)
    {
        while (results.Count <= index) results.Add(default);
        results[index] = result;
    }
});

는요.source을 사용하다이치 됩니다.TResult[]어레이를 잠그지 않고 병렬로 업데이트합니다.

TResult[] results = new TResult[source.Count];

Parallel.For(0, source.Count, parallelOptions, i =>
{
    results[i] = GetResult(source[i]);
});

에는 태스크 장벽이 되어 있기 의 모든 입니다.results어레이는 현재 스레드(표준)에서 표시됩니다.

이렇게 하면 됩니다.BlockingCollection그럴 수 있어요. finishedProxies뭇매를 맞다

BlockingCollection<string> finishedProxies = new BlockingCollection<string>();

항목을 추가하려면 다음과 같이 입력합니다.

finishedProxies.Add(checkResult);

작업이 완료되면 콘텐츠에서 목록을 만들 수 있습니다.

언급URL : https://stackoverflow.com/questions/15400133/when-to-use-blockingcollection-and-when-concurrentbag-instead-of-listt