Übersicht über BlockingCollectionBlockingCollection Overview

BlockingCollection<T> ist eine threadsichere Auflistungsklasse, die die folgenden Features bietet:BlockingCollection<T> is a thread-safe collection class that provides the following features:

  • Eine Implementierung des Producer-Consumer-Musters.An implementation of the Producer-Consumer pattern.

  • Gleichzeitiges Hinzufügen und Entfernen von Elementen aus mehreren Threads.Concurrent adding and taking of items from multiple threads.

  • Optionale maximale Kapazität.Optional maximum capacity.

  • Einfüge- und Löschvorgänge, die blockiert werden, wenn die Auflistung leer oder voll ist.Insertion and removal operations that block when collection is empty or full.

  • „Versuchs“-Einfüge- und Löschvorgänge, die nicht oder nur für eine angegebene Zeitspanne blockiert werden.Insertion and removal "try" operations that do not block or that block up to a specified period of time.

  • Kapselt jeden Auflistungstyp, der IProducerConsumerCollection<T> implementiert.Encapsulates any collection type that implements IProducerConsumerCollection<T>

  • Abbruch mit Abbruchtoken.Cancellation with cancellation tokens.

  • Zwei Arten von Enumeration mit foreach (For Each in Visual Basic):Two kinds of enumeration with foreach (For Each in Visual Basic):

    1. Schreibgeschützte Enumeration.Read-only enumeration.

    2. Enumeration, in deren Verlauf Elemente entfernt werden.Enumeration that removes items as they are enumerated.

Unterstützung von Begrenzen und BlockierenBounding and Blocking Support

BlockingCollection<T> unterstützt das Begrenzen und BlockierenBlockingCollection<T> supports bounding and blocking. Begrenzen bedeutet, dass Sie die maximale Kapazität der Auflistung festlegen können.Bounding means you can set the maximum capacity of the collection. Begrenzen ist in bestimmten Szenarien wichtig, da es Ihnen ermöglicht, die maximale Größe der Auflistung im Arbeitsspeicher zu steuern, und es verhindert, dass die erzeugenden Threads sich zu weit vor die verbrauchenden Threads bewegen.Bounding is important in certain scenarios because it enables you to control the maximum size of the collection in memory, and it prevents the producing threads from moving too far ahead of the consuming threads.

Mehrere Threads oder Tasks können gleichzeitig der Auflistung Elemente hinzufügen, und wenn die Auflistung die angegebene maximale Kapazität erreicht, werden die erzeugenden Threads blockiert, bis ein Element entfernt wird.Multiple threads or tasks can add items to the collection concurrently, and if the collection reaches its specified maximum capacity, the producing threads will block until an item is removed. Mehrere Consumer können gleichzeitig Elemente entfernen, und wenn die Auflistung leer ist, werden die verbrauchenden Threads blockiert, bis ein Producer ein Element hinzufügt.Multiple consumers can remove items concurrently, and if the collection becomes empty, the consuming threads will block until a producer adds an item. Ein Producer-Thread kann CompleteAdding aufrufen, um anzuzeigen, dass keine Elemente mehr hinzugefügt werden.A producing thread can call CompleteAdding to indicate that no more items will be added. Consumer überwachen die IsCompleted-Eigenschaft, um zu wissen, wann die Auflistung leer ist, und keine Elemente mehr hinzugefügt werden.Consumers monitor the IsCompleted property to know when the collection is empty and no more items will be added. Das folgende Beispiel zeigt eine einfache BlockingCollection mit einer begrenzten Kapazität von 100.The following example shows a simple BlockingCollection with a bounded capacity of 100. Ein Producer-Task fügt der Auflistung Elemente hinzu, solange eine externe Bedingung wahr ist, und ruft dann CompleteAdding auf.A producer task adds items to the collection as long as some external condition is true, and then calls CompleteAdding. Der Consumer-Task entnimmt Elemente, bis die IsCompleted-Eigenschaft wahr ist.The consumer task takes items until the IsCompleted property is true.

// A bounded collection. It can hold no more 
// than 100 items at once.
BlockingCollection<Data> dataItems = new BlockingCollection<Data>(100);


// A simple blocking consumer with no cancellation.
Task.Run(() => 
{
    while (!dataItems.IsCompleted)
    {
        
        Data data = null;
        // Blocks if number.Count == 0
        // IOE means that Take() was called on a completed collection.
        // Some other thread can call CompleteAdding after we pass the
        // IsCompleted check but before we call Take. 
        // In this example, we can simply catch the exception since the 
        // loop will break on the next iteration.
        try
        {
            data = dataItems.Take();
        }
        catch (InvalidOperationException) { }

        if (data != null)
        {
            Process(data);
        }
    }
    Console.WriteLine("\r\nNo more items to take.");
});

// A simple blocking producer with no cancellation.
Task.Run(() =>
{
    while (moreItemsToAdd)
    {
        Data data = GetData();
        // Blocks if numbers.Count == dataItems.BoundedCapacity
        dataItems.Add(data);
    }
    // Let consumer know we are done.
    dataItems.CompleteAdding();
});

' A bounded collection. It can hold no more 
' than 100 items at once.
Dim dataItems = New BlockingCollection(Of Data)(100)

' A simple blocking consumer with no cancellation.
Task.Factory.StartNew(Sub()
                          While dataItems.IsCompleted = False
                              Dim dataItem As Data = Nothing
                              Try
                                  dataItem = dataItems.Take()
                              Catch e As InvalidOperationException
                                  ' IOE means that Take() was called on a completed collection.
                                  ' In this example, we can simply catch the exception since the 
                                  ' loop will break on the next iteration.
                              End Try
                              If (dataItem IsNot Nothing) Then
                                  Process(dataItem)
                              End If
                          End While
                          Console.WriteLine(vbCrLf & "No more items to take.")
                      End Sub)

' A simple blocking producer with no cancellation.
Task.Factory.StartNew(Sub()
                          While moreItemsToAdd = True
                              Dim item As Data = GetData()

                              ' Blocks if numbers.Count = dataItems.BoundedCapacity
                              dataItems.Add(item)
                          End While

                          ' Let consumer know we are done.
                          dataItems.CompleteAdding()
                      End Sub)

Ein vollständiges Beispiel finden Sie unter Gewusst wie: Hinzufügen und Entfernen von einzelnen Elementen zu bzw. aus einer BlockingCollection.For a complete example, see How to: Add and Take Items Individually from a BlockingCollection.

Zeitgesteuerte BlockierungsvorgängeTimed Blocking Operations

In zeitgesteuerten TryAdd- und TryTake-Blockierungsvorgängen, die für begrenzte Sammlungen durchgeführt werden, versucht die Methode, ein Element hinzuzufügen oder zu entnehmen.In timed blocking TryAdd and TryTake operations on bounded collections, the method tries to add or take an item. Wenn ein Element verfügbar ist, wird es in die Variable eingesetzt, die durch Verweis übergeben wurde, und die Methode gibt WAHR zurück.If an item is available it is placed into the variable that was passed in by reference, and the method returns true. Wenn nach einer angegebenen Timeoutfrist kein Element abgerufen wird, gibt die Methode FALSCH zurück.If no item is retrieved after a specified time-out period the method returns false. Der Thread ist dann vor dem erneuten Versuch, auf die Auflistung zuzugreifen, frei für andere nützliche Aufgaben.The thread is then free to do some other useful work before trying again to access the collection. Ein Beispiel für das zeitgesteuerte Blockieren des Zugriffs ist das zweite Beispiel unter Gewusst wie: Hinzufügen und Entfernen von einzelnen Elementen zu bzw. aus einer BlockingCollection.For an example of timed blocking access, see the second example in How to: Add and Take Items Individually from a BlockingCollection.

Abbrechen von Hinzufüge- und NehmevorgängenCancelling Add and Take Operations

Hinzufüge- und Nehmevorgänge werden in der Regel in einer Schleife ausgeführt.Add and Take operations are typically performed in a loop. Sie können eine Schleife durch die Übergabe eines CancellationToken an die TryAdd- oder TryTake-Methode abbrechen und dann den Wert der IsCancellationRequested-Eigenschaft des Tokens in jeder Iteration überprüfen.You can cancel a loop by passing in a CancellationToken to the TryAdd or TryTake method, and then checking the value of the token's IsCancellationRequested property on each iteration. Wenn der Wert WAHR ist, liegt es an Ihnen, auf die Abbruchanforderung durch Bereinigen aller Ressourcen und Beenden der Schleife zu reagieren.If the value is true, then it is up to you to respond the cancellation request by cleaning up any resources and exiting the loop. Das folgende Beispiel zeigt eine Überladung von TryAdd, die ein Abbruchtoken entgegennimmt, und den Code, der es verwendet:The following example shows an overload of TryAdd that takes a cancellation token, and the code that uses it:

do
{
    // Cancellation causes OCE. We know how to handle it.
    try
    {
        success = bc.TryAdd(itemToAdd, 2, ct);
    }
    catch (OperationCanceledException)
    {
        bc.CompleteAdding();
        break;
    }
    //...
} while (moreItems == true);
Do While moreItems = True
    ' Cancellation causes OCE. We know how to handle it.
    Try
        success = bc.TryAdd(itemToAdd, 2, ct)
    Catch ex As OperationCanceledException
        bc.CompleteAdding()
        Exit Do
    End Try
Loop

Ein Beispiel für das Hinzufügen von Abbruchunterstützung ist das zweite Beispiel unter Gewusst wie: Hinzufügen und Entfernen von einzelnen Elementen zu bzw. aus einer BlockingCollection.For an example of how to add cancellation support, see the second example in How to: Add and Take Items Individually from a BlockingCollection.

Angeben des AuflistungstypsSpecifying the Collection Type

Beim Erstellen einer BlockingCollection<T> können Sie nicht nur die begrenzte Kapazität angeben, sondern auch den Typ der zu verwendenden Auflistung.When you create a BlockingCollection<T>, you can specify not only the bounded capacity but also the type of collection to use. Sie könnten z.B. einen ConcurrentQueue<T> für das First-in-First-out-Verhalten (FIFO) oder einen ConcurrentStack<T> für das Last-in-First-out-Verhalten (LIFO) angeben.For example, you could specify a ConcurrentQueue<T> for first in-first out (FIFO) behavior, or a ConcurrentStack<T> for last in-first out (LIFO) behavior. Sie können jede Auflistungsklasse verwenden, die die IProducerConsumerCollection<T>-Schnittstelle implementiert.You can use any collection class that implements the IProducerConsumerCollection<T> interface. Der standardmäßige Auflistungstyp für BlockingCollection<T> ist ConcurrentQueue<T>.The default collection type for BlockingCollection<T> is ConcurrentQueue<T>. Das folgende Codebeispiel veranschaulicht das Erstellen einer BlockingCollection<T> von Zeichenfolgen, die eine Kapazität von 1000 hat und einen ConcurrentBag<T> verwendet:The following code example shows how to create a BlockingCollection<T> of strings that has a capacity of 1000 and uses a ConcurrentBag<T>:

Dim bc = New BlockingCollection(Of String)(New ConcurrentBag(Of String()), 1000)  
BlockingCollection<string> bc = new BlockingCollection<string>(new ConcurrentBag<string>(), 1000 );  

Weitere Informationen finden Sie unter Gewusst wie: Hinzufügen von Begrenzungs- und Blockadefunktionen zu einer Auflistung.For more information, see How to: Add Bounding and Blocking Functionality to a Collection.

IEnumerable-UnterstützungIEnumerable Support

BlockingCollection<T> bietet eine GetConsumingEnumerable-Methode, mit der Consumer eine foreach (For Each in Visual BasicVisual Basic) verwenden können, um Elemente zu entfernen, bis die Sammlung abgeschlossen ist, d.h. bis sie leer ist und keine Elemente mehr hinzugefügt werden.BlockingCollection<T> provides a GetConsumingEnumerable method that enables consumers to use foreach (For Each in Visual BasicVisual Basic) to remove items until the collection is completed, which means it is empty and no more items will be added. Weitere Informationen finden Sie unter Gewusst wie: Entfernen von Elementen in einer BlockingCollection mit ForEach.For more information, see How to: Use ForEach to Remove Items in a BlockingCollection.

Verwenden vieler BlockingCollections als eine einzigeUsing Many BlockingCollections As One

Für Szenarien, in denen ein Consumer Elemente aus mehreren Auflistungen gleichzeitig nehmen muss, können Sie Arrays von BlockingCollection<T> erstellen und statische Methoden wie TakeFromAny und AddToAny verwenden, die Elemente beliebigen Auflistungen im Array hinzufügen bzw. daraus entnehmen.For scenarios in which a consumer needs to take items from multiple collections simultaneously, you can create arrays of BlockingCollection<T> and use the static methods such as TakeFromAny and AddToAny that will add to or take from any of the collections in the array. Wenn eine Auflistung blockiert wird, versucht die Methode sofort, eine andere zu verwenden, bis sie eine findet, die den Vorgang ausführen kann.If one collection is blocking, the method immediately tries another until it finds one that can perform the operation. Weitere Informationen finden Sie unter Gewusst wie: Verwenden von Arrays mit blockierenden Auflistungen in einer Pipeline.For more information, see How to: Use Arrays of Blocking Collections in a Pipeline.

Siehe auchSee Also

System.Collections.Concurrent
Auflistungen und DatenstrukturenCollections and Data Structures
Threadsichere SammlungenThread-Safe Collections