Datenfluss (Task Parallel Library)Dataflow (Task Parallel Library)

Die Task Parallel Library (TPL) stellt Datenflusskomponenten bereit, um die Stabilität von nebenläufigkeitsfähigen Anwendungen zu erhöhen.The Task Parallel Library (TPL) provides dataflow components to help increase the robustness of concurrency-enabled applications. Diese Datenflusskomponenten werden zusammen als TPL-Datenflussbibliothek bezeichnet.These dataflow components are collectively referred to as the TPL Dataflow Library. Dieses Datenflussmodell begünstigt die akteurbasierte Programmierung durch eine prozessinterne Nachrichtenübergabe für simple Datenfluss- und Pipelineaufgaben.This dataflow model promotes actor-based programming by providing in-process message passing for coarse-grained dataflow and pipelining tasks. Die Datenflusskomponenten basieren auf den Typen und der Planungsinfrastruktur der TPL und sind in die C#-, Visual Basic- und F#-Sprachunterstützung für asynchrone Programmierung integriert.The dataflow components build on the types and scheduling infrastructure of the TPL and integrate with the C#, Visual Basic, and F# language support for asynchronous programming. Diese Datenflusskomponenten sind hilfreich, wenn mehrere Vorgänge vorliegen, die asynchron miteinander kommunizieren müssen, oder wenn Sie Daten verarbeiten möchten, die gerade verfügbar werden.These dataflow components are useful when you have multiple operations that must communicate with one another asynchronously or when you want to process data as it becomes available. Denken Sie beispielsweise an eine Anwendung, die Bilddaten von einer Webcam verarbeitet.For example, consider an application that processes image data from a web camera. Durch das Datenflussmodell kann die Anwendung Bildframes verarbeiten, sobald diese verfügbar sind.By using the dataflow model, the application can process image frames as they become available. Wenn die Anwendung Bildframes beispielsweise durch Lichtkorrektur oder Rote-Augen-Reduktion aufbessert, können Sie eine Pipeline von Datenflusskomponenten erstellen.If the application enhances image frames, for example, by performing light correction or red-eye reduction, you can create a pipeline of dataflow components. Jede Phase der Pipeline kann grober strukturierte Parallelitätsfunktionen verwenden, wie z. B. die von der TPL bereitgestellten Funktionen zum Transformieren des Bilds.Each stage of the pipeline might use more coarse-grained parallelism functionality, such as the functionality that is provided by the TPL, to transform the image.

Dieses Dokument enthält eine Übersicht über die TPL-Datenflussbibliothek.This document provides an overview of the TPL Dataflow Library. Es bietet Informationen über das Programmiermodell, die vordefinierten Datenflussblocktypen sowie die Konfiguration der Datenflussblöcke für die speziellen Anforderungen Ihrer Anwendungen.It describes the programming model, the predefined dataflow block types, and how to configure dataflow blocks to meet the specific requirements of your applications.

Hinweis

Die TPL-Datenflussbibliothek (System.Threading.Tasks.Dataflow-Namespace) wird nicht mit .NET ausgeliefert.The TPL Dataflow Library (the System.Threading.Tasks.Dataflow namespace) is not distributed with .NET. Öffnen Sie zum Installieren des System.Threading.Tasks.Dataflow-Namespace in Visual Studio Ihr Projekt, wählen Sie im Menü Projekt die Option NuGet-Pakete verwalten aus, und suchen Sie online nach dem System.Threading.Tasks.Dataflow-Paket.To install the System.Threading.Tasks.Dataflow namespace in Visual Studio, open your project, choose Manage NuGet Packages from the Project menu, and search online for the System.Threading.Tasks.Dataflow package. Alternativ können Sie es mithilfe der .Net Core-CLI installieren und dotnet add package System.Threading.Tasks.Dataflow ausführen.Alternatively, to install it using the .Net Core CLI, run dotnet add package System.Threading.Tasks.Dataflow.

Dieses Dokument enthält folgende Abschnitte:This document contains the following sections:

ProgrammiermodellProgramming Model

Die TPL-Datenflussbibliothek bietet eine Grundlage für die Nachrichtenübergabe und die Parallelisierung CPU-intensiver und E/A-intensiver Anwendungen mit hohem Durchsatz und niedriger Latenz.The TPL Dataflow Library provides a foundation for message passing and parallelizing CPU-intensive and I/O-intensive applications that have high throughput and low latency. Außerdem erhalten Sie damit explizite Kontrolle darüber, wie Daten gepuffert und im System übermittelt werden.It also gives you explicit control over how data is buffered and moves around the system. Stellen Sie sich zum besseren Verständnis des Datenflussprogrammiermodells eine Anwendung vor, die Bilder asynchron vom Datenträger lädt und ein Kompositum dieser Bilder erstellt.To better understand the dataflow programming model, consider an application that asynchronously loads images from disk and creates a composite of those images. Herkömmliche Programmiermodelle erfordern in der Regel die Verwendung von Rückrufen und Synchronisierungsobjekten wie Sperren, um Aufgaben und den Zugriff auf freigegebene Daten zu koordinieren.Traditional programming models typically require that you use callbacks and synchronization objects, such as locks, to coordinate tasks and access to shared data. Mit dem Datenflussprogrammiermodell können Sie Datenflussobjekte erstellen, die Bilder beim Lesen vom Datenträger verarbeiten.By using the dataflow programming model, you can create dataflow objects that process images as they are read from disk. Unter dem Datenflussmodell deklarieren Sie, wie Daten behandelt werden, sobald diese verfügbar werden, und legen außerdem Abhängigkeiten zwischen Daten fest.Under the dataflow model, you declare how data is handled when it becomes available, and also any dependencies between data. Da die Laufzeit Abhängigkeiten zwischen Daten verwaltet, können Sie häufig die Anforderung vermeiden, Zugriff auf freigegebene Daten synchronisieren zu müssen.Because the runtime manages dependencies between data, you can often avoid the requirement to synchronize access to shared data. Da die Arbeit von der Laufzeit basierend auf dem asynchronen Eintreffen von Daten geplant wird, können Reaktionsgeschwindigkeit und Durchsatz des Datenflusses verbessert werden, indem die zugrunde liegenden Threads effizient verwaltet werden.In addition, because the runtime schedules work based on the asynchronous arrival of data, dataflow can improve responsiveness and throughput by efficiently managing the underlying threads. Ein Beispiel, bei dem mit dem Datenflussprogrammiermodell eine Bildverarbeitung in einer Windows Forms-Anwendung implementiert wird, finden Sie unter Walkthrough: Using Dataflow in a Windows Forms Application (Exemplarische Vorgehensweise: Verwenden von Datenflüssen in einer Windows Forms-Anwendung).For an example that uses the dataflow programming model to implement image processing in a Windows Forms application, see Walkthrough: Using Dataflow in a Windows Forms Application.

Quellen und ZieleSources and Targets

Die TPL-Datenflussbibliothek besteht aus Datenflussblöcken, bei denen es sich um Datenstrukturen handelt, die Daten puffern und verarbeiten.The TPL Dataflow Library consists of dataflow blocks, which are data structures that buffer and process data. Die TPL definiert drei Arten von Datenflussblöcken: Quellblöcke, Zielblöcke und Weitergabeblöcke.The TPL defines three kinds of dataflow blocks: source blocks, target blocks, and propagator blocks. Ein Quellblock fungiert als Datenquelle, aus der gelesen werden kann.A source block acts as a source of data and can be read from. Ein Zielblock fungiert als Datenempfänger, in den geschrieben werden kann.A target block acts as a receiver of data and can be written to. Ein Weitergabeblock fungiert als Quellblock und als Zielblock, aus dem gelesen und in den geschrieben werden kann.A propagator block acts as both a source block and a target block, and can be read from and written to. Die TPL definiert die System.Threading.Tasks.Dataflow.ISourceBlock<TOutput>-Schnittstelle, um Quellen darzustellen, System.Threading.Tasks.Dataflow.ITargetBlock<TInput>, um Ziele darzustellen, und System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput,TOutput>, um Weitergaben darzustellen.The TPL defines the System.Threading.Tasks.Dataflow.ISourceBlock<TOutput> interface to represent sources, System.Threading.Tasks.Dataflow.ITargetBlock<TInput> to represent targets, and System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput,TOutput> to represent propagators. IPropagatorBlock<TInput,TOutput> erbt von ISourceBlock<TOutput> und ITargetBlock<TInput>.IPropagatorBlock<TInput,TOutput> inherits from both ISourceBlock<TOutput>, and ITargetBlock<TInput>.

Die TPL-Datenflussbibliothek enthält mehrere vordefinierte Datenflussblocktypen, die die Schnittstellen ISourceBlock<TOutput>, ITargetBlock<TInput> und IPropagatorBlock<TInput,TOutput> implementieren.The TPL Dataflow Library provides several predefined dataflow block types that implement the ISourceBlock<TOutput>, ITargetBlock<TInput>, and IPropagatorBlock<TInput,TOutput> interfaces. Diese Datenflussblocktypen werden in diesem Dokument im Abschnitt Vordefinierte Datenflussblocktypen beschrieben.These dataflow block types are described in this document in the section Predefined Dataflow Block Types.

Verbinden von BlöckenConnecting Blocks

Sie können Datenflussblöcke mit Formularpipelines (lineare Sequenzen von Datenflussblöcken) oder Netzwerken (Diagramme von Datenflussblöcken) verbinden.You can connect dataflow blocks to form pipelines, which are linear sequences of dataflow blocks, or networks, which are graphs of dataflow blocks. Eine Pipeline ist eine Form von Netzwerk.A pipeline is one form of network. In einer Pipeline oder einem Netzwerk geben Quellen asynchron Daten an Ziele weiter, sobald diese Daten verfügbar werden.In a pipeline or network, sources asynchronously propagate data to targets as that data becomes available. Die ISourceBlock<TOutput>.LinkTo-Methode verknüpft einen Quelldatenflussblock mit einem Zielblock.The ISourceBlock<TOutput>.LinkTo method links a source dataflow block to a target block. Eine Quelle kann mit null oder mehr Zielen verknüpft werden. Ziele können mit null oder mehr Quellen verknüpft werden.A source can be linked to zero or more targets; targets can be linked from zero or more sources. Sie können Datenflussblöcke in einer Pipeline oder einem Netzwerk gleichzeitig hinzufügen oder entfernen.You can add or remove dataflow blocks to or from a pipeline or network concurrently. Die vordefinierten Datenflussblocktypen behandeln alle Threadsicherheitsaspekte bezüglich Verknüpfungen und des Lösens von Verknüpfungen.The predefined dataflow block types handle all thread-safety aspects of linking and unlinking.

Ein Beispiel für die Verbindung von Datenflussblöcken zum Erstellen einer einfachen Pipeline finden Sie unter Walkthrough: Creating a Dataflow Pipeline (Exemplarische Vorgehensweise: Erstellen einer Datenflusspipeline).For an example that connects dataflow blocks to form a basic pipeline, see Walkthrough: Creating a Dataflow Pipeline. Ein Beispiel für die Verbindung von Datenflussblöcken zum Erstellen eines komplexeren Netzwerks finden Sie unter Walkthrough: Using Dataflow in a Windows Forms Application (Exemplarische Vorgehensweise: Verwenden von Datenflüssen in einer Windows Forms-Anwendung).For an example that connects dataflow blocks to form a more complex network, see Walkthrough: Using Dataflow in a Windows Forms Application. Ein Beispiel, bei dem die Verknüpfung eines Ziels mit einer Quelle gelöst wird, nachdem die Quelle dem Ziel eine Nachricht anbietet, finden Sie unter Vorgehensweise: Aufheben der Verknüpfungen von Datenflussblöcken.For an example that unlinks a target from a source after the source offers the target a message, see How to: Unlink Dataflow Blocks.

FilternFiltering

Wenn Sie die ISourceBlock<TOutput>.LinkTo-Methode aufrufen, um eine Quelle mit einem Ziel zu verknüpfen, können Sie einen Delegaten bereitstellen, der anhand des Werts einer Nachricht bestimmt, ob der Zielblock die Nachricht annimmt oder ablehnt.When you call the ISourceBlock<TOutput>.LinkTo method to link a source to a target, you can supply a delegate that determines whether the target block accepts or rejects a message based on the value of that message. Dieser Filtermechanismus ist eine hilfreiche Möglichkeit, um sicherzustellen, dass nur bestimmte Werte von einem Datenflussblock empfangen werden.This filtering mechanism is a useful way to guarantee that a dataflow block receives only certain values. Für die meisten der vordefinierten Datenflussblocktypen gilt, dass eine Nachricht von der Quelle dem nächsten Ziel angeboten wird, wenn ein Quellblock mit mehreren Zielblöcken verbunden ist und ein Zielblock die Nachricht ablehnt.For most of the predefined dataflow block types, if a source block is connected to multiple target blocks, when a target block rejects a message, the source offers that message to the next target. Die Reihenfolge, in der Nachrichten von einer Quelle Zielen angeboten werden, wird durch die Quelle definiert und kann je nach Typ der Quelle variieren.The order in which a source offers messages to targets is defined by the source and can vary according to the type of the source. Die meisten Quellblocktypen bieten eine Nachricht nicht weiter an, nachdem diese von einem Ziel akzeptiert wurde.Most source block types stop offering a message after one target accepts that message. Eine Ausnahme dieser Regel ist die BroadcastBlock<T>-Klasse, die jede Nachricht allen Zielen anbietet, auch wenn einige Ziele die Nachricht ablehnen.One exception to this rule is the BroadcastBlock<T> class, which offers each message to all targets, even if some targets reject the message. Ein Beispiel, bei dem durch Filterung nur bestimmte Nachrichten verarbeitet werden, finden Sie unter Walkthrough: Using Dataflow in a Windows Forms Application (Exemplarische Vorgehensweise: Verwenden von Datenflüssen in einer Windows Forms-Anwendung).For an example that uses filtering to process only certain messages, see Walkthrough: Using Dataflow in a Windows Forms Application.

Wichtig

Da jeder vordefinierte Quelldatenflussblocktyp sicherstellt, dass Nachrichten in der Reihenfolge weitergegeben werden, in der sie empfangen werden, muss jede Nachricht vom Quellblock gelesen werden, bevor der Quellblock die nächste Nachricht verarbeiten kann.Because each predefined source dataflow block type guarantees that messages are propagated out in the order in which they are received, every message must be read from the source block before the source block can process the next message. Wenn Sie daher Filter verwenden, um mehrere Ziele mit einer Quelle zu verbinden, sollten Sie sicherstellen, dass jede Nachricht von mindestens einem Zielblock empfangen wird.Therefore, when you use filtering to connect multiple targets to a source, make sure that at least one target block receives each message. Andernfalls kann bei der Anwendung ein Deadlock auftreten.Otherwise, your application might deadlock.

NachrichtenübergabeMessage Passing

Das Datenflussprogrammiermodell bezieht sich auf das Konzept der Nachrichtenübergabe, bei dem unabhängige Komponenten eines Programms miteinander kommunizieren, indem sie Nachrichten senden.The dataflow programming model is related to the concept of message passing, where independent components of a program communicate with one another by sending messages. Eine Möglichkeit, Nachrichten zwischen Anwendungskomponenten weiterzugeben, besteht darin, die Post- und die DataflowBlock.SendAsync-Methode aufzurufen, um Nachrichten an Zieldatenflussblöcke zu senden (Post agiert synchron, SendAsync agiert asynchron), und die Receive-, ReceiveAsync- und TryReceive-Methoden aufzurufen, um Nachrichten von Quellblöcken zu empfangen.One way to propagate messages among application components is to call the Post and DataflowBlock.SendAsync methods to send messages to target dataflow blocks post (Post acts synchronously; SendAsync acts asynchronously) and the Receive, ReceiveAsync, and TryReceive methods to receive messages from source blocks. Sie können diese Methoden mit Datenflusspipelines oder -netzwerken kombinieren, indem Sie Eingabedaten an den Hauptknoten (ein Zielblock) senden und Ausgabedaten vom Terminalknoten der Pipeline bzw. von den Terminalknoten des Netzwerks (ein oder mehrere Quellblöcke) empfangen.You can combine these methods with dataflow pipelines or networks by sending input data to the head node (a target block), and receiving output data from the terminal node of the pipeline or the terminal nodes of the network (one or more source blocks). Sie können auch die Choose-Methode verwenden, um aus der ersten der bereitgestellten Quellen zu lesen, die Daten zur Verfügung stellt, und Aktionen für diese Daten ausführen.You can also use the Choose method to read from the first of the provided sources that has data available and perform action on that data.

Quellblöcke bieten Zielblöcken Daten an, indem die ITargetBlock<TInput>.OfferMessage-Methode aufgerufen wird.Source blocks offer data to target blocks by calling the ITargetBlock<TInput>.OfferMessage method. Der Zielblock reagiert auf eine angebotene Nachricht auf eine von drei Arten: Er kann die Nachricht akzeptieren, ablehnen oder zurückstellen.The target block responds to an offered message in one of three ways: it can accept the message, decline the message, or postpone the message. Wenn das Ziel die Nachricht akzeptiert, gibt die OfferMessage-Methode Accepted zurück.When the target accepts the message, the OfferMessage method returns Accepted. Wenn das Ziel die Nachricht ablehnt, gibt die OfferMessage-Methode Declined zurück.When the target declines the message, the OfferMessage method returns Declined. Wenn das Ziel erfordert, dass es keine weiteren Nachrichten mehr von der Quelle empfängt, gibt die OfferMessage-Methode DecliningPermanently zurück.When the target requires that it no longer receives any messages from the source, OfferMessage returns DecliningPermanently. Die vordefinierten Quellblocktypen bieten verknüpften Zielen keine Nachrichten an, nachdem ein solcher Rückgabewert empfangen wird, und die Verknüpfung zu solchen Zielen wird automatisch gelöst.The predefined source block types do not offer messages to linked targets after such a return value is received, and they automatically unlink from such targets.

Wenn ein Zielblock die Nachricht für die spätere Verwendung zurückstellt, gibt die OfferMessage-Methode Postponed zurück.When a target block postpones the message for later use, the OfferMessage method returns Postponed. Ein Zielblock, der eine Nachricht zurückstellt, kann später die Methode ISourceBlock<TOutput>.ReserveMessage aufrufen, um zu versuchen, die angebotene Nachricht zu reservieren.A target block that postpones a message can later call the ISourceBlock<TOutput>.ReserveMessage method to try to reserve the offered message. In diesem Moment ist die Nachricht entweder weiterhin verfügbar und kann vom Zielblock verwendet werden, oder die Nachricht wurde von einem anderen Ziel angenommen.At this point, the message is either still available and can be used by the target block, or the message has been taken by another target. Wenn der Zielblock die Nachricht später benötigt oder die Nachricht nicht mehr benötigt, wird die ISourceBlock<TOutput>.ConsumeMessage- bzw. die ReleaseReservation-Methode aufgerufen.When the target block later requires the message or no longer needs the message, it calls the ISourceBlock<TOutput>.ConsumeMessage or ReleaseReservation method, respectively. Nachrichtenreservierung wird in der Regel von Datenflussblocktypen verwendet, die sich im nicht gierigen Modus befinden.Message reservation is typically used by the dataflow block types that operate in non-greedy mode. "Nicht gieriger Modus" wird weiter unten in diesem Dokument erläutert.Non-greedy mode is explained later in this document. Anstatt eine zurückgestellte Nachricht zu reservieren, kann ein Zielblock auch die ISourceBlock<TOutput>.ConsumeMessage-Methode verwenden, um zu versuchen, die zurückgestellte Nachricht direkt zu verarbeiten.Instead of reserving a postponed message, a target block can also use the ISourceBlock<TOutput>.ConsumeMessage method to attempt to directly consume the postponed message.

Abschluss von DatenflussblöckenDataflow Block Completion

Datenflussblöcke unterstützen auch das Konzept des Abschlusses.Dataflow blocks also support the concept of completion. Ein Datenflussblock, der sich im abgeschlossenen Zustand befindet, führt keine weitere Arbeit mehr aus.A dataflow block that is in the completed state does not perform any further work. Jeder Datenflussblock verfügt über ein zugehöriges System.Threading.Tasks.Task-Objekt, das als Abschlussaufgabe bezeichnet wird und den Abschlusszustand des Blocks darstellt.Each dataflow block has an associated System.Threading.Tasks.Task object, known as a completion task, that represents the completion status of the block. Da Sie mithilfe von Abschlussaufgaben darauf warten können, dass ein Task-Objekt abgeschlossen wird, können Sie auf den Abschluss von einem oder mehreren Terminalknoten eines Datenflussnetzwerks warten.Because you can wait for a Task object to finish, by using completion tasks, you can wait for one or more terminal nodes of a dataflow network to finish. Die IDataflowBlock-Schnittstelle definiert die Complete-Methode, die den Datenflussblock über eine abzuschließende Anforderung informiert, sowie die Completion-Eigenschaft, die die Abschlussaufgabe für den Datenflussblock zurückgibt.The IDataflowBlock interface defines the Complete method, which informs the dataflow block of a request for it to complete, and the Completion property, which returns the completion task for the dataflow block. ISourceBlock<TOutput> und ITargetBlock<TInput> erben beide von der IDataflowBlock-Schnittstelle.Both ISourceBlock<TOutput> and ITargetBlock<TInput> inherit the IDataflowBlock interface.

Es gibt zwei Möglichkeiten, um zu bestimmen, ob ein Datenflussblock ohne Fehler abgeschlossen wurde, ob mindestens ein Fehler aufgetreten ist oder ob er abgebrochen wurde.There are two ways to determine whether a dataflow block completed without error, encountered one or more errors, or was canceled. Die erste Möglichkeit besteht darin, die Task.Wait-Methode für die Abschlussaufgabe in einem try---Block (catch``Try``Catch in Visual Basic) aufzurufen.The first way is to call the Task.Wait method on the completion task in a try-catch block (Try-Catch in Visual Basic). Im folgenden Beispiel wird ein ActionBlock<TInput>-Objekt erstellt, das ArgumentOutOfRangeException auslöst, wenn der Eingabewert kleiner als null ist.The following example creates an ActionBlock<TInput> object that throws ArgumentOutOfRangeException if its input value is less than zero. AggregateException wird ausgelöst, wenn in diesem Beispiel Wait für die Abschlussaufgabe aufgerufen wird.AggregateException is thrown when this example calls Wait on the completion task. Der Zugriff auf ArgumentOutOfRangeException erfolgt über die InnerExceptions-Eigenschaft des AggregateException-Objekts.The ArgumentOutOfRangeException is accessed through the InnerExceptions property of the AggregateException object.

// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
   Console.WriteLine("n = {0}", n);
   if (n < 0)
   {
      throw new ArgumentOutOfRangeException();
   }
});

// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();

// Wait for completion in a try/catch block.
try
{
   throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
   // If an unhandled exception occurs during dataflow processing, all
   // exceptions are propagated through an AggregateException object.
   ae.Handle(e =>
   {
      Console.WriteLine("Encountered {0}: {1}", 
         e.GetType().Name, e.Message);
      return true;
   });
}

/* Output:
n = 0
n = -1
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
 of valid values.
*/
         ' Create an ActionBlock<int> object that prints its input
         ' and throws ArgumentOutOfRangeException if the input
         ' is less than zero.
         Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
             Console.WriteLine("n = {0}", n)
             If n < 0 Then
                 Throw New ArgumentOutOfRangeException()
             End If
         End Sub)

         ' Post values to the block.
         throwIfNegative.Post(0)
         throwIfNegative.Post(-1)
         throwIfNegative.Post(1)
         throwIfNegative.Post(-2)
         throwIfNegative.Complete()

         ' Wait for completion in a try/catch block.
         Try
            throwIfNegative.Completion.Wait()
         Catch ae As AggregateException
            ' If an unhandled exception occurs during dataflow processing, all
            ' exceptions are propagated through an AggregateException object.
            ae.Handle(Function(e)
                Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
                Return True
            End Function)
         End Try

'          Output:
'         n = 0
'         n = -1
'         Encountered ArgumentOutOfRangeException: Specified argument was out of the range
'          of valid values.
'         

In diesem Beispiel wird der Fall erläutert, in dem eine Ausnahme im Delegaten eines Ausführungsdatenflussblocks unbehandelt bleibt.This example demonstrates the case in which an exception goes unhandled in the delegate of an execution dataflow block. Es wird empfohlen, Ausnahmen in den Codetexten solcher Blöcke zu behandeln.We recommend that you handle exceptions in the bodies of such blocks. Wenn dies jedoch nicht möglich ist, verhält sich der Block, als ob er abgebrochen wurde, und verarbeitet keine eingehenden Nachrichten.However, if you are unable to do so, the block behaves as though it was canceled and does not process incoming messages.

Wenn ein Datenflussblock explizit abgebrochen wird, enthält das AggregateException-Objekt OperationCanceledException in der InnerExceptions-Eigenschaft.When a dataflow block is canceled explicitly, the AggregateException object contains OperationCanceledException in the InnerExceptions property. Weitere Informationen zum Abbrechen von Datenflüssen finden Sie im Abschnitt Aktivieren des Abbruchs.For more information about dataflow cancellation, see Enabling Cancellation section.

Die zweite Möglichkeit, den Abschlussstatus eines Datenflussblocks zu bestimmen, ist die Verwendung einer Fortsetzung außerhalb der Abschlussaufgabe oder die Verwendung der asynchronen Sprachfunktionen von C# und Visual Basic, um auf die Abschlussaufgabe asynchron zu warten.The second way to determine the completion status of a dataflow block is to use a continuation of the completion task, or to use the asynchronous language features of C# and Visual Basic to asynchronously wait for the completion task. Der Delegat, den Sie für die Task.ContinueWith-Methode bereitstellen, nimmt ein Task-Objekt an, das die vorangehende Aufgabe darstellt.The delegate that you provide to the Task.ContinueWith method takes a Task object that represents the antecedent task. Im Fall der Completion-Eigenschaft nimmt der Delegat für die Fortsetzung die Abschlussaufgabe selbst an.In the case of the Completion property, the delegate for the continuation takes the completion task itself. Das folgende Beispiel ähnelt dem vorherigen, es wird jedoch auch die ContinueWith-Methode verwendet, um eine Abschlussaufgabe zu erstellen, die den Status des gesamten Datenflussvorgangs ausgibt.The following example resembles the previous one, except that it also uses the ContinueWith method to create a continuation task that prints the status of the overall dataflow operation.

// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
   Console.WriteLine("n = {0}", n);
   if (n < 0)
   {
      throw new ArgumentOutOfRangeException();
   }
});

// Create a continuation task that prints the overall 
// task status to the console when the block finishes.
throwIfNegative.Completion.ContinueWith(task =>
{
   Console.WriteLine("The status of the completion task is '{0}'.", 
      task.Status);
});

// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();

// Wait for completion in a try/catch block.
try
{
   throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
   // If an unhandled exception occurs during dataflow processing, all
   // exceptions are propagated through an AggregateException object.
   ae.Handle(e =>
   {
      Console.WriteLine("Encountered {0}: {1}",
         e.GetType().Name, e.Message);
      return true;
   });
}

/* Output:
n = 0
n = -1
The status of the completion task is 'Faulted'.
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
 of valid values.
*/
         ' Create an ActionBlock<int> object that prints its input
         ' and throws ArgumentOutOfRangeException if the input
         ' is less than zero.
         Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
             Console.WriteLine("n = {0}", n)
             If n < 0 Then
                 Throw New ArgumentOutOfRangeException()
             End If
         End Sub)

         ' Create a continuation task that prints the overall 
         ' task status to the console when the block finishes.
         throwIfNegative.Completion.ContinueWith(Sub(task) Console.WriteLine("The status of the completion task is '{0}'.", task.Status))

         ' Post values to the block.
         throwIfNegative.Post(0)
         throwIfNegative.Post(-1)
         throwIfNegative.Post(1)
         throwIfNegative.Post(-2)
         throwIfNegative.Complete()

         ' Wait for completion in a try/catch block.
         Try
            throwIfNegative.Completion.Wait()
         Catch ae As AggregateException
            ' If an unhandled exception occurs during dataflow processing, all
            ' exceptions are propagated through an AggregateException object.
            ae.Handle(Function(e)
                Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
                Return True
            End Function)
         End Try

'          Output:
'         n = 0
'         n = -1
'         The status of the completion task is 'Faulted'.
'         Encountered ArgumentOutOfRangeException: Specified argument was out of the range
'          of valid values.
'         

Sie können auch Eigenschaften wie IsCanceled im Codetext der Fortsetzungsaufgabe verwenden, um zusätzliche Informationen über den Abschlussstatus eines Datenflussblocks zu ermitteln.You can also use properties such as IsCanceled in the body of the continuation task to determine additional information about the completion status of a dataflow block. Weitere Informationen zu Fortsetzungsaufgaben und deren Beziehung zum Abbruch und zur Fehlerbehandlung finden Sie unter Verketten von Aufgaben durch Fortsetzungsaufgaben, Aufgabenabbruch und Ausnahmebehandlung.For more information about continuation tasks and how they relate to cancellation and error handling, see Chaining Tasks by Using Continuation Tasks, Task Cancellation, and Exception Handling.

[Nach oben][go to top]

Vordefinierte DatenflussblocktypenPredefined Dataflow Block Types

Die TPL-Datenflussbibliothek enthält mehrere vordefinierte Datenflussblocktypen.The TPL Dataflow Library provides several predefined dataflow block types. Diese Typen sind in drei Kategorien unterteilt: Pufferblöcke, Ausführungsblöcke und Gruppierungsblöcke.These types are divided into three categories: buffering blocks, execution blocks, and grouping blocks. In den folgenden Abschnitten werden die Blocktypen dieser Kategorien beschrieben.The following sections describe the block types that make up these categories.

PufferblöckeBuffering Blocks

Pufferblöcke enthalten Daten zur Verwendung durch Datenconsumer.Buffering blocks hold data for use by data consumers. Die TPL-Datenflussbibliothek enthält drei Pufferblocktypen: System.Threading.Tasks.Dataflow.BufferBlock<T>, System.Threading.Tasks.Dataflow.BroadcastBlock<T> und System.Threading.Tasks.Dataflow.WriteOnceBlock<T>.The TPL Dataflow Library provides three buffering block types: System.Threading.Tasks.Dataflow.BufferBlock<T>, System.Threading.Tasks.Dataflow.BroadcastBlock<T>, and System.Threading.Tasks.Dataflow.WriteOnceBlock<T>.

BufferBlock(T)BufferBlock(T)

Die BufferBlock<T>-Klasse stellt eine allgemeine asynchrone Nachrichtenstruktur dar.The BufferBlock<T> class represents a general-purpose asynchronous messaging structure. Diese Klasse speichert eine FIFO-Nachrichtenwarteschlange (First In, First Out), in die mehrere Quellen Nachrichten schreiben oder aus der mehrere Ziele Nachrichten auslesen können.This class stores a first in, first out (FIFO) queue of messages that can be written to by multiple sources or read from by multiple targets. Wenn ein Ziel eine Nachricht von einem BufferBlock<T>-Objekt empfängt, wird diese Nachricht aus der Nachrichtenwarteschlange entfernt.When a target receives a message from a BufferBlock<T> object, that message is removed from the message queue. Daher können die einzelnen Nachrichten nur von einem Ziel empfangen werden, obwohl ein BufferBlock<T>-Objekt mehrere Ziele haben kann.Therefore, although a BufferBlock<T> object can have multiple targets, only one target will receive each message. Die BufferBlock<T>-Klasse ist hilfreich, wenn Sie mehrere Nachrichten an eine andere Komponente übergeben möchten und diese Komponente alle Nachrichten empfangen muss.The BufferBlock<T> class is useful when you want to pass multiple messages to another component, and that component must receive each message.

Im folgenden grundlegenden Beispiel werden mehrere Int32-Werte an ein BufferBlock<T>-Objekt gesendet und anschließend wieder aus dem Objekt gelesen.The following basic example posts several Int32 values to a BufferBlock<T> object and then reads those values back from that object.

// Create a BufferBlock<int> object.
var bufferBlock = new BufferBlock<int>();

// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
   bufferBlock.Post(i);
}

// Receive the messages back from the block.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(bufferBlock.Receive());
}

/* Output:
   0
   1
   2
 */
         ' Create a BufferBlock<int> object.
         Dim bufferBlock = New BufferBlock(Of Integer)()

         ' Post several messages to the block.
         For i As Integer = 0 To 2
            bufferBlock.Post(i)
         Next i

         ' Receive the messages back from the block.
         For i As Integer = 0 To 2
            Console.WriteLine(bufferBlock.Receive())
         Next i

'          Output:
'            0
'            1
'            2
'          

Ein vollständiges Beispiel zur Veranschaulichung, wie Nachrichten in ein BufferBlock<T>-Objekt geschrieben oder daraus gelesen werden, finden Sie unter Vorgehensweise: Schreiben und Lesen von Nachrichten in einem Datenflussblock.For a complete example that demonstrates how to write messages to and read messages from a BufferBlock<T> object, see How to: Write Messages to and Read Messages from a Dataflow Block.

BroadcastBlock(T)BroadcastBlock(T)

Die BroadcastBlock<T>-Klasse ist hilfreich, wenn mehrere Nachrichten an eine andere Komponente übergeben werden müssen, diese Komponente jedoch nur den letzten Wert benötigt.The BroadcastBlock<T> class is useful when you must pass multiple messages to another component, but that component needs only the most recent value. Diese Klasse ist darüber hinaus auch hilfreich, wenn Sie eine Nachricht an mehreren Komponenten übertragen möchten.This class is also useful when you want to broadcast a message to multiple components.

Im folgenden grundlegenden Beispiel wird ein Double-Wert an ein BroadcastBlock<T>-Objekt gesendet und dann mehrmals aus dem Objekt gelesen.The following basic example posts a Double value to a BroadcastBlock<T> object and then reads that value back from that object several times. Da Werte nicht aus BroadcastBlock<T>-Objekten entfernt werden, nachdem sie gelesen wurden, ist der gleiche Wert jedes Mal verfügbar.Because values are not removed from BroadcastBlock<T> objects after they are read, the same value is available every time.

// Create a BroadcastBlock<double> object.
var broadcastBlock = new BroadcastBlock<double>(null);

// Post a message to the block.
broadcastBlock.Post(Math.PI);

// Receive the messages back from the block several times.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(broadcastBlock.Receive());
}

/* Output:
   3.14159265358979
   3.14159265358979
   3.14159265358979
 */
         ' Create a BroadcastBlock<double> object.
         Dim broadcastBlock = New BroadcastBlock(Of Double)(Nothing)

         ' Post a message to the block.
         broadcastBlock.Post(Math.PI)

         ' Receive the messages back from the block several times.
         For i As Integer = 0 To 2
            Console.WriteLine(broadcastBlock.Receive())
         Next i

'          Output:
'            3.14159265358979
'            3.14159265358979
'            3.14159265358979
'          

Ein vollständiges Beispiel zur Veranschaulichung, wie eine Nachricht mit BroadcastBlock<T> an mehrere Zielblöcke gesendet wird, finden Sie unter Vorgehensweise: Angeben eines Taskplaners in einem Datenflussblock.For a complete example that demonstrates how to use BroadcastBlock<T> to broadcast a message to multiple target blocks, see How to: Specify a Task Scheduler in a Dataflow Block.

WriteOnceBlock(T)WriteOnceBlock(T)

Die WriteOnceBlock<T>-Klasse ähnelt der BroadcastBlock<T>-Klasse, ein WriteOnceBlock<T>-Objekt kann jedoch nur einmal hineingeschrieben werden.The WriteOnceBlock<T> class resembles the BroadcastBlock<T> class, except that a WriteOnceBlock<T> object can be written to one time only. WriteOnceBlock<T> ähnelt dem readonly-Schlüsselwort in C# (ReadOnly in Visual Basic), ein WriteOnceBlock<T>-Objekt wird jedoch unveränderlich, nachdem es einen Wert anstatt einer Konstruktion empfängt.You can think of WriteOnceBlock<T> as being similar to the C# readonly (ReadOnly in Visual Basic) keyword, except that a WriteOnceBlock<T> object becomes immutable after it receives a value instead of at construction. Wenn ein Ziel eine Nachricht von einem BroadcastBlock<T>-Objekt empfängt, wird diese Nachricht wie bei der WriteOnceBlock<T>-Klasse nicht aus diesem Objekt entfernt.Like the BroadcastBlock<T> class, when a target receives a message from a WriteOnceBlock<T> object, that message is not removed from that object. Daher empfangen mehrere Ziele eine Kopie der Nachricht.Therefore, multiple targets receive a copy of the message. Die WriteOnceBlock<T>-Klasse ist hilfreich, wenn Sie nur die erste von mehreren Nachrichten weitergeben möchten.The WriteOnceBlock<T> class is useful when you want to propagate only the first of multiple messages.

Im folgenden Beispiel werden mehrere String-Werte an ein WriteOnceBlock<T>-Objekt gesendet. Anschließend wird der Wert aus dem Objekt gelesen.The following basic example posts multiple String values to a WriteOnceBlock<T> object and then reads the value back from that object. Da in ein WriteOnceBlock<T>-Objekt nur einmal geschrieben werden kann, nachdem ein WriteOnceBlock<T>-Objekt eine Nachricht empfängt, werden nachfolgende Nachrichten verworfen.Because a WriteOnceBlock<T> object can be written to one time only, after a WriteOnceBlock<T> object receives a message, it discards subsequent messages.

// Create a WriteOnceBlock<string> object.
var writeOnceBlock = new WriteOnceBlock<string>(null);

// Post several messages to the block in parallel. The first 
// message to be received is written to the block. 
// Subsequent messages are discarded.
Parallel.Invoke(
   () => writeOnceBlock.Post("Message 1"),
   () => writeOnceBlock.Post("Message 2"),
   () => writeOnceBlock.Post("Message 3"));

// Receive the message from the block.
Console.WriteLine(writeOnceBlock.Receive());

/* Sample output:
   Message 2
 */
         ' Create a WriteOnceBlock<string> object.
         Dim writeOnceBlock = New WriteOnceBlock(Of String)(Nothing)

         ' Post several messages to the block in parallel. The first 
         ' message to be received is written to the block. 
         ' Subsequent messages are discarded.
         Parallel.Invoke(Function() writeOnceBlock.Post("Message 1"), Function() writeOnceBlock.Post("Message 2"), Function() writeOnceBlock.Post("Message 3"))

         ' Receive the message from the block.
         Console.WriteLine(writeOnceBlock.Receive())

'          Sample output:
'            Message 2
'          

Ein vollständiges Beispiel zur Veranschaulichung, wie mit WriteOnceBlock<T> der Wert des ersten abgeschlossenen Vorgangs empfangen wird, finden Sie unter Vorgehensweise: Aufheben der Verknüpfungen von Datenflussblöcken.For a complete example that demonstrates how to use WriteOnceBlock<T> to receive the value of the first operation that finishes, see How to: Unlink Dataflow Blocks.

AusführungsblöckeExecution Blocks

Ausführungsblöcke rufen einen vom Benutzer bereitgestellten Delegaten für jedes Element empfangener Daten auf.Execution blocks call a user-provided delegate for each piece of received data. Die TPL-Datenflussbibliothek enthält drei Typen von Ausführungsblöcken: ActionBlock<TInput>, System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput> und System.Threading.Tasks.Dataflow.TransformManyBlock<TInput,TOutput>.The TPL Dataflow Library provides three execution block types: ActionBlock<TInput>, System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput>, and System.Threading.Tasks.Dataflow.TransformManyBlock<TInput,TOutput>.

ActionBlock(T)ActionBlock(T)

Die ActionBlock<TInput>-Klasse ist ein Zielblock, der einen Delegaten aufruft, wenn er Daten empfängt.The ActionBlock<TInput> class is a target block that calls a delegate when it receives data. Stellen Sie sich ein ActionBlock<TInput>-Objekt als Delegaten vor, der asynchron ausgeführt wird, wenn Daten verfügbar werden.Think of a ActionBlock<TInput> object as a delegate that runs asynchronously when data becomes available. Der Delegat, den Sie für ein ActionBlock<TInput>-Objekt bereitstellen, kann vom Typ Action<T> oder vom Typ System.Func<TInput, Task> sein.The delegate that you provide to an ActionBlock<TInput> object can be of type Action<T> or type System.Func<TInput, Task>. Wenn Sie ein ActionBlock<TInput>-Objekt mit Action<T> verwenden, wird die Verarbeitung jedes Eingabeelements als abgeschlossen betrachtet, wenn der Delegat zurückgegeben wird.When you use an ActionBlock<TInput> object with Action<T>, processing of each input element is considered completed when the delegate returns. Wenn Sie ein ActionBlock<TInput>-Objekt mit System.Func<TInput, Task> verwenden, wird die Verarbeitung jedes Eingabeelements nur dann als abgeschlossen betrachtet, wenn das zurückgegebene Task-Objekt abgeschlossen ist.When you use an ActionBlock<TInput> object with System.Func<TInput, Task>, processing of each input element is considered completed only when the returned Task object is completed. Mit diesen beiden Mechanismen können Sie ActionBlock<TInput> zur synchronen und asynchronen Verarbeitung der einzelnen Eingabeelemente verwenden.By using these two mechanisms, you can use ActionBlock<TInput> for both synchronous and asynchronous processing of each input element.

Im folgenden grundlegenden Beispiel werden mehrere Int32-Werte an ein ActionBlock<TInput>-Objekt gesendet.The following basic example posts multiple Int32 values to an ActionBlock<TInput> object. Das ActionBlock<TInput>-Objekt gibt diese Werte in der Konsole aus.The ActionBlock<TInput> object prints those values to the console. Im Beispiel wird der Block dann in den abgeschlossenen Zustand versetzt, und es wird gewartet, bis alle Datenflussaufgaben abgeschlossen sind.This example then sets the block to the completed state and waits for all dataflow tasks to finish.

// Create an ActionBlock<int> object that prints values
// to the console.
var actionBlock = new ActionBlock<int>(n => Console.WriteLine(n));

// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
   actionBlock.Post(i * 10);
}

// Set the block to the completed state and wait for all 
// tasks to finish.
actionBlock.Complete();
actionBlock.Completion.Wait();

/* Output:
   0
   10
   20
 */
         ' Create an ActionBlock<int> object that prints values
         ' to the console.
         Dim actionBlock = New ActionBlock(Of Integer)(Function(n) WriteLine(n))

         ' Post several messages to the block.
         For i As Integer = 0 To 2
            actionBlock.Post(i * 10)
         Next i

         ' Set the block to the completed state and wait for all 
         ' tasks to finish.
         actionBlock.Complete()
         actionBlock.Completion.Wait()

'          Output:
'            0
'            10
'            20
'          

Ausführliche Beispiele für die Verwendung von Delegaten mit der ActionBlock<TInput>-Klasse finden Sie unter Vorgehensweise: Ausführen einer Aktion, wenn ein Datenflussblock Daten empfängt.For complete examples that demonstrate how to use delegates with the ActionBlock<TInput> class, see How to: Perform Action When a Dataflow Block Receives Data.

TransformBlock(TInput, TOutput)TransformBlock(TInput, TOutput)

Die TransformBlock<TInput,TOutput>-Klasse ähnelt der ActionBlock<TInput>-Klasse, sie fungiert jedoch als Quelle und als Ziel.The TransformBlock<TInput,TOutput> class resembles the ActionBlock<TInput> class, except that it acts as both a source and as a target. Der Delegat, den Sie an ein TransformBlock<TInput,TOutput>-Objekt übergeben, gibt einen Wert vom Typ TOutput zurück.The delegate that you pass to a TransformBlock<TInput,TOutput> object returns a value of type TOutput. Der Delegat, den Sie für ein TransformBlock<TInput,TOutput>-Objekt bereitstellen, kann vom Typ System.Func<TInput, TOutput> oder vom Typ System.Func<TInput, Task<TOutput>> sein.The delegate that you provide to a TransformBlock<TInput,TOutput> object can be of type System.Func<TInput, TOutput> or type System.Func<TInput, Task<TOutput>>. Wenn Sie ein TransformBlock<TInput,TOutput>-Objekt mit System.Func<TInput, TOutput> verwenden, wird die Verarbeitung jedes Eingabeelements als abgeschlossen betrachtet, wenn der Delegat zurückgegeben wird.When you use a TransformBlock<TInput,TOutput> object with System.Func<TInput, TOutput>, processing of each input element is considered completed when the delegate returns. Wenn Sie ein TransformBlock<TInput,TOutput>-Objekt mit System.Func<TInput, Task<TOutput>> verwenden, wird die Verarbeitung jedes Eingabeelements nur dann als abgeschlossen betrachtet, wenn das zurückgegebene Task<TResult>-Objekt abgeschlossen ist.When you use a TransformBlock<TInput,TOutput> object used with System.Func<TInput, Task<TOutput>>, processing of each input element is considered completed only when the returned Task<TResult> object is completed. Wie bei ActionBlock<TInput> können Sie mit diesen beiden Mechanismen TransformBlock<TInput,TOutput> zur synchronen und asynchronen Verarbeitung der einzelnen Eingabeelemente verwenden.As with ActionBlock<TInput>, by using these two mechanisms, you can use TransformBlock<TInput,TOutput> for both synchronous and asynchronous processing of each input element.

Im folgenden grundlegenden Beispiel wird ein TransformBlock<TInput,TOutput>-Objekt erstellt, das die Quadratwurzel seiner Eingabe berechnet.The following basic example creates a TransformBlock<TInput,TOutput> object that computes the square root of its input. Das TransformBlock<TInput,TOutput>-Objekt nimmt Int32-Werte als Eingabe an und erzeugt Double-Werte als Ausgabe.The TransformBlock<TInput,TOutput> object takes Int32 values as input and produces Double values as output.

// Create a TransformBlock<int, double> object that 
// computes the square root of its input.
var transformBlock = new TransformBlock<int, double>(n => Math.Sqrt(n));

// Post several messages to the block.
transformBlock.Post(10);
transformBlock.Post(20);
transformBlock.Post(30);

// Read the output messages from the block.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(transformBlock.Receive());
}

/* Output:
   3.16227766016838
   4.47213595499958
   5.47722557505166
 */
         ' Create a TransformBlock<int, double> object that 
         ' computes the square root of its input.
         Dim transformBlock = New TransformBlock(Of Integer, Double)(Function(n) Math.Sqrt(n))

         ' Post several messages to the block.
         transformBlock.Post(10)
         transformBlock.Post(20)
         transformBlock.Post(30)

         ' Read the output messages from the block.
         For i As Integer = 0 To 2
            Console.WriteLine(transformBlock.Receive())
         Next i

'          Output:
'            3.16227766016838
'            4.47213595499958
'            5.47722557505166
'          

Ausführliche Beispiele für die Verwendung von TransformBlock<TInput,TOutput> in einem Netzwerk von Datenflussblöcken, das eine Bildverarbeitung in einer Windows Forms-Anwendung ausführt, finden Sie unter Walkthrough: Using Dataflow in a Windows Forms Application (Exemplarische Vorgehensweise: Verwenden von Datenflüssen in einer Windows Forms-Anwendung).For complete examples that uses TransformBlock<TInput,TOutput> in a network of dataflow blocks that performs image processing in a Windows Forms application, see Walkthrough: Using Dataflow in a Windows Forms Application.

TransformManyBlock(TInput, TOutput)TransformManyBlock(TInput, TOutput)

Die TransformManyBlock<TInput,TOutput>-Klasse ähnelt der TransformBlock<TInput,TOutput>-Klasse, außer dass TransformManyBlock<TInput,TOutput> null oder mehr Ausgabewerte für jeden Eingabewert erzeugt, anstatt nur eines Ausgabewerts für jeden Eingabewert.The TransformManyBlock<TInput,TOutput> class resembles the TransformBlock<TInput,TOutput> class, except that TransformManyBlock<TInput,TOutput> produces zero or more output values for each input value, instead of only one output value for each input value. Der Delegat, den Sie für ein TransformManyBlock<TInput,TOutput>-Objekt bereitstellen, kann vom Typ System.Func<TInput, IEnumerable<TOutput>> oder vom Typ System.Func<TInput, Task<IEnumerable<TOutput>>> sein.The delegate that you provide to a TransformManyBlock<TInput,TOutput> object can be of type System.Func<TInput, IEnumerable<TOutput>> or type System.Func<TInput, Task<IEnumerable<TOutput>>>. Wenn Sie ein TransformManyBlock<TInput,TOutput>-Objekt mit System.Func<TInput, IEnumerable<TOutput>> verwenden, wird die Verarbeitung jedes Eingabeelements als abgeschlossen betrachtet, wenn der Delegat zurückgegeben wird.When you use a TransformManyBlock<TInput,TOutput> object with System.Func<TInput, IEnumerable<TOutput>>, processing of each input element is considered completed when the delegate returns. Wenn Sie ein TransformManyBlock<TInput,TOutput>-Objekt mit System.Func<TInput, Task<IEnumerable<TOutput>>> verwenden, wird die Verarbeitung jedes Eingabeelements nur dann als abgeschlossen betrachtet, wenn das zurückgegebene System.Threading.Tasks.Task<IEnumerable<TOutput>>-Objekt abgeschlossen ist.When you use a TransformManyBlock<TInput,TOutput> object with System.Func<TInput, Task<IEnumerable<TOutput>>>, processing of each input element is considered complete only when the returned System.Threading.Tasks.Task<IEnumerable<TOutput>> object is completed.

Im folgenden grundlegenden Beispiel wird ein TransformManyBlock<TInput,TOutput>-Objekt erstellt, das Zeichenfolgen in ihre einzelnen Zeichensequenzen aufteilt.The following basic example creates a TransformManyBlock<TInput,TOutput> object that splits strings into their individual character sequences. Das TransformManyBlock<TInput,TOutput>-Objekt nimmt String-Werte als Eingabe an und erzeugt Char-Werte als Ausgabe.The TransformManyBlock<TInput,TOutput> object takes String values as input and produces Char values as output.

// Create a TransformManyBlock<string, char> object that splits
// a string into its individual characters.
var transformManyBlock = new TransformManyBlock<string, char>(
   s => s.ToCharArray());

// Post two messages to the first block.
transformManyBlock.Post("Hello");
transformManyBlock.Post("World");

// Receive all output values from the block.
for (int i = 0; i < ("Hello" + "World").Length; i++)
{
   Console.WriteLine(transformManyBlock.Receive());
}

/* Output:
   H
   e
   l
   l
   o
   W
   o
   r
   l
   d
 */
         ' Create a TransformManyBlock<string, char> object that splits
         ' a string into its individual characters.
         Dim transformManyBlock = New TransformManyBlock(Of String, Char)(Function(s) s.ToCharArray())

         ' Post two messages to the first block.
         transformManyBlock.Post("Hello")
         transformManyBlock.Post("World")

         ' Receive all output values from the block.
         For i As Integer = 0 To ("Hello" & "World").Length - 1
            Console.WriteLine(transformManyBlock.Receive())
         Next i

'          Output:
'            H
'            e
'            l
'            l
'            o
'            W
'            o
'            r
'            l
'            d
'          

Ausführliche Beispiele, bei denen mit TransformManyBlock<TInput,TOutput> mehrere unabhängige Ausgaben für jede Eingabe in einer Datenflusspipeline erzeugt werden, finden Sie unter Walkthrough: Creating a Dataflow Pipeline (Exemplarische Vorgehensweise: Erstellen einer Datenflusspipeline).For complete examples that use TransformManyBlock<TInput,TOutput> to produce multiple independent outputs for each input in a dataflow pipeline, see Walkthrough: Creating a Dataflow Pipeline.

Grad der ParallelitätDegree of Parallelism

Jedes ActionBlock<TInput>-, TransformBlock<TInput,TOutput>- und TransformManyBlock<TInput,TOutput>-Objekt puffert eingehende Nachrichten, bis der Block bereit für die Verarbeitung ist.Every ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput> object buffers input messages until the block is ready to process them. In der Standardeinstellung verarbeiten diese Klassen Nachrichten nacheinander in der Reihenfolge, in der sie empfangen werden.By default, these classes process messages in the order in which they are received, one message at a time. Sie können auch den Grad der Parallelität angeben, sodass ActionBlock<TInput>-, TransformBlock<TInput,TOutput>- und TransformManyBlock<TInput,TOutput>-Objekte mehrere Nachrichten gleichzeitig verarbeiten können.You can also specify the degree of parallelism to enable ActionBlock<TInput>, TransformBlock<TInput,TOutput> and TransformManyBlock<TInput,TOutput> objects to process multiple messages concurrently. Weitere Informationen über die gleichzeitige Ausführung finden Sie im Abschnitt "Festlegen des Grads der Parallelität" weiter unten in diesem Dokument.For more information about concurrent execution, see the section Specifying the Degree of Parallelism later in this document. Ein Beispiel, bei dem der Grad der Parallelität so festgelegt wird, dass ein Ausführungsdatenflussblock mehrere Nachrichten gleichzeitig verarbeiten kann, finden Sie unter Vorgehensweise: Festlegen des Parallelitätsgrads in einem Datenflussblock.For an example that sets the degree of parallelism to enable an execution dataflow block to process more than one message at a time, see How to: Specify the Degree of Parallelism in a Dataflow Block.

Übersicht über DelegattypenSummary of Delegate Types

In der folgenden Tabelle sind die Delegattypen zusammengefasst, die Sie für ActionBlock<TInput>-, TransformBlock<TInput,TOutput>- und TransformManyBlock<TInput,TOutput>-Objekte bereitstellen können.The following table summarizes the delegate types that you can provide to ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput> objects. In dieser Tabelle wird auch angegeben, ob der Delegattyp synchron oder asynchron arbeitet.This table also specifies whether the delegate type operates synchronously or asynchronously.

TypType Synchroner DelegattypSynchronous Delegate Type Asynchroner DelegattypAsynchronous Delegate Type
ActionBlock<TInput> System.Action System.Func<TInput, Task>
TransformBlock<TInput,TOutput> System.Func<TInput, TOutput> System.Func<TInput, Task<TOutput>>
TransformManyBlock<TInput,TOutput> System.Func<TInput, IEnumerable<TOutput>> System.Func<TInput, Task<IEnumerable<TOutput>>>

Sie können auch Lambda-Ausdrücke verwenden, wenn Sie mit Ausführungsblocktypen arbeiten.You can also use lambda expressions when you work with execution block types. Ein Beispiel für die Verwendung eines Lambda-Ausdrucks mit einem Ausführungsblock finden Sie unter Vorgehensweise: Ausführen einer Aktion, wenn ein Datenflussblock Daten empfängt.For an example that shows how to use a lambda expression with an execution block, see How to: Perform Action When a Dataflow Block Receives Data.

GruppierungsblöckeGrouping Blocks

Gruppierungsblöcke kombinieren Daten aus einer oder mehreren Quellen und unter verschiedenen Einschränkungen.Grouping blocks combine data from one or more sources and under various constraints. Die TPL-Datenflussbibliothek enthält drei Typen von Gruppierungsblöcken: BatchBlock<T>, JoinBlock<T1,T2> und BatchedJoinBlock<T1,T2>.The TPL Dataflow Library provides three join block types: BatchBlock<T>, JoinBlock<T1,T2>, and BatchedJoinBlock<T1,T2>.

BatchBlock(T)BatchBlock(T)

Die BatchBlock<T>-Klasse kombiniert Sätze von Eingabedaten, die als Batches bezeichnet werden, in Arrays von Ausgabedaten.The BatchBlock<T> class combines sets of input data, which are known as batches, into arrays of output data. Beim Erstellen eines BatchBlock<T>-Objekts geben Sie die Größe von jedem Batch an.You specify the size of each batch when you create a BatchBlock<T> object. Wenn das BatchBlock<T>-Objekt die angegebene Anzahl von Eingabeelementen empfängt, wird ein Array mit diesen Elementen asynchron weitergegeben.When the BatchBlock<T> object receives the specified count of input elements, it asynchronously propagates out an array that contains those elements. Wenn ein BatchBlock<T>-Objekt in den abgeschlossenen Zustand versetzt wird, jedoch nicht genügend Elemente zum Bilden eines Batches enthält, wird ein abschließendes Array mit den restlichen Eingabeelementen weitergegeben.If a BatchBlock<T> object is set to the completed state but does not contain enough elements to form a batch, it propagates out a final array that contains the remaining input elements.

Die BatchBlock<T>-Klasse arbeitet entweder im gierigen oder im nicht gierigen Modus.The BatchBlock<T> class operates in either greedy or non-greedy mode. Im gierigen Modus (Standard) nimmt ein BatchBlock<T>-Objekt jede Nachricht an, die angeboten wird, und gibt ein Array weiter, nachdem die angegebene Anzahl von Elementen empfangen wurde.In greedy mode, which is the default, a BatchBlock<T> object accepts every message that it is offered and propagates out an array after it receives the specified count of elements. Im nicht gierigen Modus stellt ein BatchBlock<T>-Objekt alle eingehenden Nachrichten zurück, bis dem Block genügend Nachrichten von Quellen angeboten wurden, um einen Batch zu bilden.In non-greedy mode, a BatchBlock<T> object postpones all incoming messages until enough sources have offered messages to the block to form a batch. Der gierige Modus erzielt in der Regel eine bessere Leistung als der nicht gierige Modus, da er weniger Verarbeitungsaufwand erfordert.Greedy mode typically performs better than non-greedy mode because it requires less processing overhead. Sie können den nicht gierigen Modus jedoch verwenden, wenn Sie die Nutzung von mehreren Quellen auf atomische Weise koordinieren müssen.However, you can use non-greedy mode when you must coordinate consumption from multiple sources in an atomic fashion. Legen Sie den nicht gierigen Modus fest, indem Sie Greedy auf False im dataflowBlockOptions Parameter im BatchBlock<T>-Konstruktor festlegen.Specify non-greedy mode by setting Greedy to False in the dataflowBlockOptions parameter in the BatchBlock<T> constructor.

Im folgenden grundlegenden Beispiel werden mehrere Int32-Werte an ein BatchBlock<T>-Objekt gesendet, das zehn Elemente in einem Batch enthält.The following basic example posts several Int32 values to a BatchBlock<T> object that holds ten elements in a batch. Um sicherzustellen, dass alle Werte aus BatchBlock<T> weitergegeben werden, wird in diesem Beispiel die Complete-Methode aufgerufen.To guarantee that all values propagate out of the BatchBlock<T>, this example calls the Complete method. Die Complete-Methode legt das BatchBlock<T>-Objekt auf den abgeschlossenen Zustand fest. Daher werden vom BatchBlock<T>-Objekt alle verbleibenden Elemente in einem abschließenden Batch weitergegeben.The Complete method sets the BatchBlock<T> object to the completed state, and therefore, the BatchBlock<T> object propagates out any remaining elements as a final batch.

// Create a BatchBlock<int> object that holds ten
// elements per batch.
var batchBlock = new BatchBlock<int>(10);

// Post several values to the block.
for (int i = 0; i < 13; i++)
{
   batchBlock.Post(i);
}
// Set the block to the completed state. This causes
// the block to propagate out any any remaining
// values as a final batch.
batchBlock.Complete();

// Print the sum of both batches.

Console.WriteLine("The sum of the elements in batch 1 is {0}.",
   batchBlock.Receive().Sum());

Console.WriteLine("The sum of the elements in batch 2 is {0}.",
   batchBlock.Receive().Sum());

/* Output:
   The sum of the elements in batch 1 is 45.
   The sum of the elements in batch 2 is 33.
 */
         ' Create a BatchBlock<int> object that holds ten
         ' elements per batch.
         Dim batchBlock = New BatchBlock(Of Integer)(10)

         ' Post several values to the block.
         For i As Integer = 0 To 12
            batchBlock.Post(i)
         Next i
         ' Set the block to the completed state. This causes
         ' the block to propagate out any any remaining
         ' values as a final batch.
         batchBlock.Complete()

         ' Print the sum of both batches.

         Console.WriteLine("The sum of the elements in batch 1 is {0}.", batchBlock.Receive().Sum())

         Console.WriteLine("The sum of the elements in batch 2 is {0}.", batchBlock.Receive().Sum())

'          Output:
'            The sum of the elements in batch 1 is 45.
'            The sum of the elements in batch 2 is 33.
'          

Ein vollständiges Beispiel für die Verwendung von BatchBlock<T> zur Verbesserung der Effizienz von Datenbankeinfügevorgängen finden Sie unter Exemplarische Vorgehensweise: Effizienzverbesserung durch Verwendung von BatchBlock und BatchedJoinBlock.For a complete example that uses BatchBlock<T> to improve the efficiency of database insert operations, see Walkthrough: Using BatchBlock and BatchedJoinBlock to Improve Efficiency.

JoinBlock(T1, T2, ...)JoinBlock(T1, T2, ...)

Die JoinBlock<T1,T2>- und die JoinBlock<T1,T2,T3>-Klasse sammeln Eingabeelemente und geben System.Tuple<T1,T2>- oder System.Tuple<T1,T2,T3>-Objekte weiter, die diese Elemente enthalten.The JoinBlock<T1,T2> and JoinBlock<T1,T2,T3> classes collect input elements and propagate out System.Tuple<T1,T2> or System.Tuple<T1,T2,T3> objects that contain those elements. Die JoinBlock<T1,T2>- und die JoinBlock<T1,T2,T3>-Klasse erben nicht von ITargetBlock<TInput>.The JoinBlock<T1,T2> and JoinBlock<T1,T2,T3> classes do not inherit from ITargetBlock<TInput>. Stattdessen stellen sie die Eigenschaften Target1, Target2 und Target3 bereit, die ITargetBlock<TInput> implementieren.Instead, they provide properties, Target1, Target2, and Target3, that implement ITargetBlock<TInput>.

Wie BatchBlock<T> arbeiten auch JoinBlock<T1,T2> und JoinBlock<T1,T2,T3> entweder im gierigen oder im nicht gierigen Modus.Like BatchBlock<T>, JoinBlock<T1,T2> and JoinBlock<T1,T2,T3> operate in either greedy or non-greedy mode. Im gierigen Modus (Standard) nimmt ein JoinBlock<T1,T2>- oder JoinBlock<T1,T2,T3>-Objekt jede Nachricht an, die angeboten wird, und gibt ein Tupel weiter, nachdem jedes der zugehörigen Ziele mindestens eine Nachricht empfangen hat.In greedy mode, which is the default, a JoinBlock<T1,T2> or JoinBlock<T1,T2,T3> object accepts every message that it is offered and propagates out a tuple after each of its targets receives at least one message. Im nicht gierigen Modus stellt ein JoinBlock<T1,T2>- oder JoinBlock<T1,T2,T3>-Objekt alle eingehenden Nachrichten zurück, bis allen Zielen die Daten angeboten wurden, die zum Erstellen eines Tupels erforderlich sind.In non-greedy mode, a JoinBlock<T1,T2> or JoinBlock<T1,T2,T3> object postpones all incoming messages until all targets have been offered the data that is required to create a tuple. An diesem Punkt initiiert der Block ein Zweiphasencommit-Protokoll, um alle erforderlichen Elemente aus den Quellen atomar abzurufen.At this point, the block engages in a two-phase commit protocol to atomically retrieve all required items from the sources. Durch diese Zurückstellung ist es möglich, dass eine andere Entität die Daten in der Zwischenzeit nutzt, sodass das gesamte System mit der Verarbeitung fortschreitet.This postponement makes it possible for another entity to consume the data in the meantime, to allow the overall system to make forward progress.

Das folgende grundlegende Beispiel zeigt einen Fall, in dem ein JoinBlock<T1,T2,T3>-Objekt mehrere Daten benötigt, einen Wert zu berechnen.The following basic example demonstrates a case in which a JoinBlock<T1,T2,T3> object requires multiple data to compute a value. In diesem Beispiel wird ein JoinBlock<T1,T2,T3>-Objekt erstellt, das zwei Int32-Werte und einen Char-Wert erfordert, um eine arithmetische Operation durchzuführen.This example creates a JoinBlock<T1,T2,T3> object that requires two Int32 values and a Char value to perform an arithmetic operation.

// Create a JoinBlock<int, int, char> object that requires
// two numbers and an operator.
var joinBlock = new JoinBlock<int, int, char>();

// Post two values to each target of the join.

joinBlock.Target1.Post(3);
joinBlock.Target1.Post(6);

joinBlock.Target2.Post(5);
joinBlock.Target2.Post(4);

joinBlock.Target3.Post('+');
joinBlock.Target3.Post('-');

// Receive each group of values and apply the operator part
// to the number parts.

for (int i = 0; i < 2; i++)
{
   var data = joinBlock.Receive();
   switch (data.Item3)
   {
      case '+':
         Console.WriteLine("{0} + {1} = {2}",
            data.Item1, data.Item2, data.Item1 + data.Item2);
         break;
      case '-':
         Console.WriteLine("{0} - {1} = {2}",
            data.Item1, data.Item2, data.Item1 - data.Item2);
         break;
      default:
         Console.WriteLine("Unknown operator '{0}'.", data.Item3);
         break;
   }
}

/* Output:
   3 + 5 = 8
   6 - 4 = 2
 */
         ' Create a JoinBlock<int, int, char> object that requires
         ' two numbers and an operator.
         Dim joinBlock = New JoinBlock(Of Integer, Integer, Char)()

         ' Post two values to each target of the join.

         joinBlock.Target1.Post(3)
         joinBlock.Target1.Post(6)

         joinBlock.Target2.Post(5)
         joinBlock.Target2.Post(4)

         joinBlock.Target3.Post("+"c)
         joinBlock.Target3.Post("-"c)

         ' Receive each group of values and apply the operator part
         ' to the number parts.

         For i As Integer = 0 To 1
            Dim data = joinBlock.Receive()
            Select Case data.Item3
               Case "+"c
                  Console.WriteLine("{0} + {1} = {2}", data.Item1, data.Item2, data.Item1 + data.Item2)
               Case "-"c
                  Console.WriteLine("{0} - {1} = {2}", data.Item1, data.Item2, data.Item1 - data.Item2)
               Case Else
                  Console.WriteLine("Unknown operator '{0}'.", data.Item3)
            End Select
         Next i

'          Output:
'            3 + 5 = 8
'            6 - 4 = 2
'          

Ein vollständiges Beispiel für die Verwendung von JoinBlock<T1,T2>-Objekten im nicht gierigen Modus zur kooperativen Nutzung einer Ressource finden Sie unter Vorgehensweise: Verwenden von JoinBlock zum Lesen aus mehreren Quellen.For a complete example that uses JoinBlock<T1,T2> objects in non-greedy mode to cooperatively share a resource, see How to: Use JoinBlock to Read Data From Multiple Sources.

BatchedJoinBlock(T1, T2, ...)BatchedJoinBlock(T1, T2, ...)

Die BatchedJoinBlock<T1,T2>- und die BatchedJoinBlock<T1,T2,T3>-Klasse sammeln Batches von Eingabeelementen und geben System.Tuple(IList(T1), IList(T2))- oder System.Tuple(IList(T1), IList(T2), IList(T3))-Objekte weiter, die diese Elemente enthalten.The BatchedJoinBlock<T1,T2> and BatchedJoinBlock<T1,T2,T3> classes collect batches of input elements and propagate out System.Tuple(IList(T1), IList(T2)) or System.Tuple(IList(T1), IList(T2), IList(T3)) objects that contain those elements. Stellen Sie sich BatchedJoinBlock<T1,T2> als eine Kombination aus BatchBlock<T> und JoinBlock<T1,T2> vor.Think of BatchedJoinBlock<T1,T2> as a combination of BatchBlock<T> and JoinBlock<T1,T2>. Beim Erstellen eines BatchedJoinBlock<T1,T2>-Objekts geben Sie die Größe von jedem Batch an.Specify the size of each batch when you create a BatchedJoinBlock<T1,T2> object. BatchedJoinBlock<T1,T2> stellt außerdem die Eigenschaften Target1 und Target2 bereit, die ITargetBlock<TInput> implementieren.BatchedJoinBlock<T1,T2> also provides properties, Target1 and Target2, that implement ITargetBlock<TInput>. Wenn die angegebene Anzahl von Eingabeelementen auf allen Zielen empfangen wurde, gibt das BatchedJoinBlock<T1,T2>-Objekt ein System.Tuple(IList(T1), IList(T2))-Objekt asynchron weiter, das die Elemente enthält.When the specified count of input elements are received from across all targets, the BatchedJoinBlock<T1,T2> object asynchronously propagates out a System.Tuple(IList(T1), IList(T2)) object that contains those elements.

Im folgenden grundlegenden Beispiel wird ein BatchedJoinBlock<T1,T2>-Objekt erstellt, das Ergebnisse, Int32-Werte und Fehler enthält, bei denen es sich um Exception-Objekte handelt.The following basic example creates a BatchedJoinBlock<T1,T2> object that holds results, Int32 values, and errors that are Exception objects. In diesem Beispiel werden mehrere Vorgänge durchgeführt. Ergebnisse werden in die Target1-Eigenschaft und Fehler in die Target2-Eigenschaft des BatchedJoinBlock<T1,T2>-Objekts geschrieben.This example performs multiple operations and writes results to the Target1 property, and errors to the Target2 property, of the BatchedJoinBlock<T1,T2> object. Da die Anzahl der erfolgreichen und fehlgeschlagenen Vorgänge im Voraus unbekannt ist, ermöglichen die IList<T>-Objekte, dass jedes Ziel null oder mehr Werte empfängt.Because the count of successful and failed operations is unknown in advance, the IList<T> objects enable each target to receive zero or more values.

 // For demonstration, create a Func<int, int> that 
 // returns its argument, or throws ArgumentOutOfRangeException
 // if the argument is less than zero.
 Func<int, int> DoWork = n =>
 {
    if (n < 0)
       throw new ArgumentOutOfRangeException();
    return n;
 };

 // Create a BatchedJoinBlock<int, Exception> object that holds 
 // seven elements per batch.
 var batchedJoinBlock = new BatchedJoinBlock<int, Exception>(7);

 // Post several items to the block.
 foreach (int i in new int[] { 5, 6, -7, -22, 13, 55, 0 })
 {
    try
    {
       // Post the result of the worker to the 
       // first target of the block.
       batchedJoinBlock.Target1.Post(DoWork(i));
    }
    catch (ArgumentOutOfRangeException e) 
    {
       // If an error occurred, post the Exception to the 
       // second target of the block.
       batchedJoinBlock.Target2.Post(e); 
    }
 }

 // Read the results from the block.
 var results = batchedJoinBlock.Receive();

 // Print the results to the console.

 // Print the results.
 foreach (int n in results.Item1)
 {
    Console.WriteLine(n);
 }
 // Print failures.
 foreach (Exception e in results.Item2)
 {
    Console.WriteLine(e.Message);
 }

 /* Output:
    5
    6
    13
    55
    0
    Specified argument was out of the range of valid values.
    Specified argument was out of the range of valid values.
  */
         ' For demonstration, create a Func<int, int> that 
         ' returns its argument, or throws ArgumentOutOfRangeException
         ' if the argument is less than zero.
         Dim DoWork As Func(Of Integer, Integer) = Function(n)
            If n < 0 Then
               Throw New ArgumentOutOfRangeException()
            End If
            Return n
         End Function

         ' Create a BatchedJoinBlock<int, Exception> object that holds 
         ' seven elements per batch.
         Dim batchedJoinBlock = New BatchedJoinBlock(Of Integer, Exception)(7)

         ' Post several items to the block.
         For Each i As Integer In New Integer() { 5, 6, -7, -22, 13, 55, 0 }
            Try
               ' Post the result of the worker to the 
               ' first target of the block.
               batchedJoinBlock.Target1.Post(DoWork(i))
            Catch e As ArgumentOutOfRangeException
               ' If an error occurred, post the Exception to the 
               ' second target of the block.
               batchedJoinBlock.Target2.Post(e)
            End Try
         Next i

         ' Read the results from the block.
         Dim results = batchedJoinBlock.Receive()

         ' Print the results to the console.

         ' Print the results.
         For Each n As Integer In results.Item1
            Console.WriteLine(n)
         Next n
         ' Print failures.
         For Each e As Exception In results.Item2
            Console.WriteLine(e.Message)
         Next e

'          Output:
'            5
'            6
'            13
'            55
'            0
'            Specified argument was out of the range of valid values.
'            Specified argument was out of the range of valid values.
'          

Ein vollständiges Beispiel, bei dem mit BatchedJoinBlock<T1,T2> die Ergebnisse und Ausnahmen erfasst werden, die beim Lesen des Programms aus einer Datenbank auftreten, finden Sie unter Exemplarische Vorgehensweise: Effizienzverbesserung durch Verwendung von BatchBlock und BatchedJoinBlock.For a complete example that uses BatchedJoinBlock<T1,T2> to capture both the results and any exceptions that occur while the program reads from a database, see Walkthrough: Using BatchBlock and BatchedJoinBlock to Improve Efficiency.

[Nach oben][go to top]

Konfigurieren des DatenflussblockverhaltensConfiguring Dataflow Block Behavior

Sie können zusätzliche Optionen aktivieren, indem Sie ein System.Threading.Tasks.Dataflow.DataflowBlockOptions-Objekt für den Konstruktor von Datenflussblocktypen bereitstellen.You can enable additional options by providing a System.Threading.Tasks.Dataflow.DataflowBlockOptions object to the constructor of dataflow block types. Diese Optionen steuern das Verhalten wie z. B. den Planer, der die zugrunde liegende Aufgabe und den Grad der Parallelität verwaltet.These options control behavior such the scheduler that manages the underlying task and the degree of parallelism. DataflowBlockOptions verfügt außerdem über abgeleitete Typen, die das Verhalten für bestimmte Datenflussblocktypen festlegen.The DataflowBlockOptions also has derived types that specify behavior that is specific to certain dataflow block types. In der folgenden Tabelle ist zusammengefasst, welcher Optionstyp den einzelnen Datenflussblocktypen zugeordnet ist.The following table summarizes which options type is associated with each dataflow block type.

DatenflussblocktypDataflow Block Type DataflowBlockOptions-TypDataflowBlockOptions type
BufferBlock<T> DataflowBlockOptions
BroadcastBlock<T> DataflowBlockOptions
WriteOnceBlock<T> DataflowBlockOptions
ActionBlock<TInput> ExecutionDataflowBlockOptions
TransformBlock<TInput,TOutput> ExecutionDataflowBlockOptions
TransformManyBlock<TInput,TOutput> ExecutionDataflowBlockOptions
BatchBlock<T> GroupingDataflowBlockOptions
JoinBlock<T1,T2> GroupingDataflowBlockOptions
BatchedJoinBlock<T1,T2> GroupingDataflowBlockOptions

Die folgenden Abschnitte enthalten zusätzliche Informationen über die wichtigen Arten von Optionen für Datenflussblöcke, die durch die Klassen System.Threading.Tasks.Dataflow.DataflowBlockOptions, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions und System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions zur Verfügung stehen.The following sections provide additional information about the important kinds of dataflow block options that are available through the System.Threading.Tasks.Dataflow.DataflowBlockOptions, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions, and System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions classes.

Festlegen des AufgabenplanersSpecifying the Task Scheduler

Jeder vordefinierte Datenflussblock verwendet den TPL-Aufgabenplanungsmechanismus zum Durchführen von Aktivitäten, wie das Weitergeben von Daten an ein Ziel, das Empfangen von Daten aus einer Quelle und das Ausführen benutzerdefinierter Delegate, wenn Daten verfügbar werden.Every predefined dataflow block uses the TPL task scheduling mechanism to perform activities such as propagating data to a target, receiving data from a source, and running user-defined delegates when data becomes available. TaskScheduler ist eine abstrakte Klasse, die einen Aufgabenplaner darstellt, der Aufgaben in Warteschlangen für Threads stellt.TaskScheduler is an abstract class that represents a task scheduler that queues tasks onto threads. Der Standardtaskplaner Default verwendet die ThreadPool-Klasse, um Arbeit in die Warteschlange zu stellen und auszuführen.The default task scheduler, Default, uses the ThreadPool class to queue and execute work. Sie können den Standardtaskplaner überschreiben, indem Sie die TaskScheduler-Eigenschaft festlegen, wenn Sie ein Datenflussblockobjekt erstellen.You can override the default task scheduler by setting the TaskScheduler property when you construct a dataflow block object.

Wenn der gleiche Aufgabenplaner mehrere Datenflussblöcke verwaltet, kann er Richtlinien für sie erzwingen.When the same task scheduler manages multiple dataflow blocks, it can enforce policies across them. Wenn beispielsweise für mehrere Datenflussblöcke jeweils der exklusive Planer des gleichen ConcurrentExclusiveSchedulerPair-Objekts als Ziel konfiguriert ist, wird die gesamte Arbeit serialisiert, die auf diesen Blöcken ausgeführt wird.For example, if multiple dataflow blocks are each configured to target the exclusive scheduler of the same ConcurrentExclusiveSchedulerPair object, all work that runs across these blocks is serialized. Wenn für diese Blöcke der parallele Planer des gleichen ConcurrentExclusiveSchedulerPair-Objekts als Ziel konfiguriert wird und dieser Planer für die maximale Nebenläufigkeitsebene konfiguriert ist, wird die gesamte Arbeit von diesen Blöcken auf diese Anzahl paralleler Vorgänge beschränkt.Similarly, if these blocks are configured to target the concurrent scheduler of the same ConcurrentExclusiveSchedulerPair object, and that scheduler is configured to have a maximum concurrency level, all work from these blocks is limited to that number of concurrent operations. Ein Beispiel, bei dem mithilfe der ConcurrentExclusiveSchedulerPair-Klasse Lesevorgänge parallel ausgeführt werden, Schreibvorgänge jedoch exklusiv von allen anderen Vorgängen erfolgen, finden Sie unter Vorgehensweise: Angeben eines Taskplaners in einem Datenflussblock.For an example that uses the ConcurrentExclusiveSchedulerPair class to enable read operations to occur in parallel, but write operations to occur exclusively of all other operations, see How to: Specify a Task Scheduler in a Dataflow Block. Weitere Informationen zum Taskplaner in der TPL finden Sie im Thema zur TaskScheduler-Klasse.For more information about task schedulers in the TPL, see the TaskScheduler class topic.

Festlegen des Grads der ParallelitätSpecifying the Degree of Parallelism

In der Standardeinstellung verarbeitet die drei Ausführungsblocktypen, die die TPL-Datenflussbibliothek bereitstellt, ActionBlock<TInput>, TransformBlock<TInput,TOutput> und TransformManyBlock<TInput,TOutput>, jeweils nur eine Nachricht.By default, the three execution block types that the TPL Dataflow Library provides, ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput>, process one message at a time. Diese Datenflussblocktypen verarbeiten Nachrichten ebenfalls in der Reihenfolge, in der sie empfangen werden.These dataflow block types also process messages in the order in which they are received. Damit diese Datenflussblöcke Nachrichten gleichzeitig verarbeiten können, muss die ExecutionDataflowBlockOptions.MaxDegreeOfParallelism-Eigenschaft beim Erstellen des Datenflussblockobjekts festgelegt werden.To enable these dataflow blocks to process messages concurrently, set the ExecutionDataflowBlockOptions.MaxDegreeOfParallelism property when you construct the dataflow block object.

Der Standardwert von MaxDegreeOfParallelism ist 1. Dadurch wird gewährleistet, dass der Datenflussblock jeweils nur eine Nachricht verarbeitet.The default value of MaxDegreeOfParallelism is 1, which guarantees that the dataflow block processes one message at a time. Durch das Festlegen dieser Eigenschaft auf einen Wert, der größer als 1 ist, kann der Datenflussblock mehrere Nachrichten gleichzeitig verarbeiten.Setting this property to a value that is larger than 1 enables the dataflow block to process multiple messages concurrently. Durch das Festlegen dieser Eigenschaft auf DataflowBlockOptions.Unbounded kann der zugrunde liegende Aufgabenplaner den maximalen Grad von Nebenläufigkeit verwalten.Setting this property to DataflowBlockOptions.Unbounded enables the underlying task scheduler to manage the maximum degree of concurrency.

Wichtig

Wenn Sie einen maximalen Grad an Parallelität angeben, der größer als 1 ist, werden mehrere Nachrichten gleichzeitig verarbeitet. Daher werden Nachrichten möglicherweise nicht in der Reihenfolge verarbeitet, in der sie empfangen werden.When you specify a maximum degree of parallelism that is larger than 1, multiple messages are processed simultaneously, and therefore messages might not be processed in the order in which they are received. Die Reihenfolge, in der die Nachrichten aus dem Block ausgegeben werden, ist jedoch mit der Reihenfolge identisch, in der sie empfangen werden.The order in which the messages are output from the block is, however, the same one in which they are received.

Da die MaxDegreeOfParallelism-Eigenschaft den maximalen Grad an Parallelität darstellt, wird der Datenflussblock u. U. mit einem geringeren Grad an Parallelität ausgeführt als angegeben.Because the MaxDegreeOfParallelism property represents the maximum degree of parallelism, the dataflow block might execute with a lesser degree of parallelism than you specify. Der Datenflussblock kann zum Erfüllen seiner Funktionsanforderungen oder aufgrund eines Mangels an verfügbaren Systemressourcen einen geringeren Grad an Parallelität verwenden.The dataflow block might use a lesser degree of parallelism to meet its functional requirements or because there is a lack of available system resources. Ein Datenflussblock wird nie mit mehr Parallelität ausgeführt als Sie angeben.A dataflow block never chooses more parallelism than you specify.

Der Wert der MaxDegreeOfParallelism-Eigenschaft ist exklusiv für jedes Datenflussblockobjekt.The value of the MaxDegreeOfParallelism property is exclusive to each dataflow block object. Wenn beispielsweise für vier Datenflussblockobjekte als maximaler Grad an Parallelität jeweils 1 angegeben wird, können u. U. alle vier Datenflussblockobjekte parallel ausgeführt werden.For example, if four dataflow block objects each specify 1 for the maximum degree of parallelism, all four dataflow block objects can potentially run in parallel.

Ein Beispiel, bei dem der maximale Grad an Parallelität so festgelegt wird, dass lang andauernde Operationen parallel ausgeführt werden können, finden Sie unter Vorgehensweise: Festlegen des Parallelitätsgrads in einem Datenflussblock.For an example that sets the maximum degree of parallelism to enable lengthy operations to occur in parallel, see How to: Specify the Degree of Parallelism in a Dataflow Block.

Festlegen der Anzahl von Nachrichten pro AufgabeSpecifying the Number of Messages per Task

Die vordefinierten Datenflussblocktypen verwenden Aufgaben, um mehrere Eingabeelemente zu verarbeiten.The predefined dataflow block types use tasks to process multiple input elements. Dadurch kann die Anzahl der zum Verarbeiten von Daten erforderlichen Aufgabenobjekte minimiert werden, sodass Anwendungen effizienter ausgeführt werden können.This helps minimize the number of task objects that are required to process data, which enables applications to run more efficiently. Wenn Daten von den Aufgaben aus einem Satz von Datenflussblöcken verarbeitet werden, müssen die Aufgaben von anderen Datenflussblöcken jedoch möglicherweise auf Verarbeitungszeit warten, indem Nachrichten in die Warteschlange gestellt werden.However, when the tasks from one set of dataflow blocks are processing data, the tasks from other dataflow blocks might need to wait for processing time by queuing messages. Legen Sie die Eigenschaft MaxMessagesPerTask fest, um eine bessere Ausgewogenheit zwischen Datenflussaufgaben zu ermöglichen.To enable better fairness among dataflow tasks, set the MaxMessagesPerTask property. Wenn MaxMessagesPerTask auf DataflowBlockOptions.Unbounded (Standard) festgelegt ist, verarbeitet die von einem Datenflussblock verwendete Aufgabe alle verfügbaren Nachrichten.When MaxMessagesPerTask is set to DataflowBlockOptions.Unbounded, which is the default, the task used by a dataflow block processes as many messages as are available. Wenn MaxMessagesPerTask auf einen anderen Wert als Unbounded festgelegt wird, verarbeitet der Datenflussblock höchstens diese Anzahl an Nachrichten pro Task-Objekt.When MaxMessagesPerTask is set to a value other than Unbounded, the dataflow block processes at most this number of messages per Task object. Obwohl das Festlegen der MaxMessagesPerTask-Eigenschaft die Ausgewogenheit zwischen Aufgaben erhöhen kann, werden vom System u. U. mehr Aufgaben als notwendig erstellt, sodass die Leistung beeinträchtigt wird.Although setting the MaxMessagesPerTask property can increase fairness among tasks, it can cause the system to create more tasks than are necessary, which can decrease performance.

Aktivieren des AbbruchsEnabling Cancellation

Die TPL bietet einen Mechanismus, durch den Aufgaben Abbrüche kooperative koordinieren können.The TPL provides a mechanism that enables tasks to coordinate cancellation in a cooperative manner. Legen Sie die CancellationToken-Eigenschaft fest, damit Datenflussblöcke diesen Abbruchmechanismus nutzen.To enable dataflow blocks to participate in this cancellation mechanism, set the CancellationToken property. Wenn dieses CancellationToken-Objekt in den abgebrochenen Zustand versetzt wird, beenden alle Datenflussblöcke, die dieses Token überwachen, die Ausführung ihres aktuellen Elements, beginnen jedoch nicht mit der Verarbeitung nachfolgender Elemente.When this CancellationToken object is set to the canceled state, all dataflow blocks that monitor this token finish execution of their current item but do not start processing subsequent items. Diese Datenflussblöcke löschen außerdem alle gepufferten Nachrichten, geben Verbindungen zu allen Quell- und Zielblöcken frei und wechseln in den abgebrochenen Zustand.These dataflow blocks also clear any buffered messages, release connections to any source and target blocks, and transition to the canceled state. Durch den Übergang in den abgebrochenen Zustand, wird die Completion-Eigenschaft der Status-Eigenschaft auf Canceled festgelegt, wenn während der Verarbeitung keine Aufnahme aufgetreten ist.By transitioning to the canceled state, the Completion property has the Status property set to Canceled, unless an exception occurred during processing. In diesem Fall wird Status auf Faulted festgelegt.In that case, Status is set to Faulted.

Ein Beispiel für die Verwendung eines Abbruchs in einer Windows Forms-Anwendung finden Sie unter Vorgehensweise: Abbrechen eines Datenflussblocks.For an example that demonstrates how to use cancellation in a Windows Forms application, see How to: Cancel a Dataflow Block. Weitere Informationen über Abbrüche in der TPL finden Sie unter Aufgabenabbruch.For more information about cancellation in the TPL, see Task Cancellation.

Festlegen von gierigem Verhalten im Vergleich zu nicht gierigem VerhaltenSpecifying Greedy Versus Non-Greedy Behavior

Mehrere Gruppierungsdatenflussblock-Typen können im gierigen oder im nicht gierigen Modus arbeiten.Several grouping dataflow block types can operate in either greedy or non-greedy mode. In der Standardeinstellung arbeiten die vordefinierten Datenflussblocktypen im gierigen Modus.By default, the predefined dataflow block types operate in greedy mode.

Bei Gruppierungsblocktypen wie JoinBlock<T1,T2> bedeutet der gierige Modus, dass Daten vom Block sofort angenommen werden, auch wenn die entsprechenden Daten, mit denen eine gemeinsame Gruppierung erfolgt, noch nicht verfügbar sind.For join block types such as JoinBlock<T1,T2>, greedy mode means that the block immediately accepts data even if the corresponding data with which to join is not yet available. Nicht gieriger Modus bedeutet, dass der Block alle eingehenden Nachrichten zurückstellt, bis eine Nachricht an jedem der zugehörigen Ziele verfügbar ist, um die Gruppierung zu vervollständigen.Non-greedy mode means that the block postpones all incoming messages until one is available on each of its targets to complete the join. Wenn eine der zurückgestellten Nachrichten nicht mehr verfügbar ist, gibt der Gruppierungsblock alle zurückgestellten Nachrichten frei und startet den Prozess neu.If any of the postponed messages are no longer available, the join block releases all postponed messages and restarts the process. Bei der BatchBlock<T>-Klasse ist das gierige und das nicht gierige Verhalten ähnlich, außer dass ein BatchBlock<T>-Objekt im nicht gierigen Modus alle eingehenden Nachrichten zurückstellt, bis genügend Nachrichten aus verschiedenen Quellen verfügbar sind, um einen Batch zu vervollständigen.For the BatchBlock<T> class, greedy and non-greedy behavior is similar, except that under non-greedy mode, a BatchBlock<T> object postpones all incoming messages until enough are available from distinct sources to complete a batch.

Legen Sie Greedy auf False fest, um den nicht gierigen Modus für einen Datenflussblock festzulegen.To specify non-greedy mode for a dataflow block, set Greedy to False. Ein Beispiel für die Verwendung des nicht gierigen Modus, sodass mehrere Gruppierungsblöcke eine Datenquelle effizienter gemeinsam verwenden können, finden Sie unter Vorgehensweise: Verwenden von JoinBlock zum Lesen aus mehreren Quellen.For an example that demonstrates how to use non-greedy mode to enable multiple join blocks to share a data source more efficiently, see How to: Use JoinBlock to Read Data From Multiple Sources.

[Nach oben][go to top]

Benutzerdefinierte DatenflussblöckeCustom Dataflow Blocks

Obwohl die TPL-Datenflussbibliothek viele vordefinierte Blocktypen bereitstellt, können Sie zusätzliche Blockstypen mit einem benutzerdefinierten Verhalten erstellen.Although the TPL Dataflow Library provides many predefined block types, you can create additional block types that perform custom behavior. Implementieren Sie direkt die ISourceBlock<TOutput>- oder die ITargetBlock<TInput>-Schnittstelle, oder verwenden Sie die Encapsulate-Methode, um einen komplexen Block zu erstellen, der das Verhalten vorhandener Blocktypen kapselt.Implement the ISourceBlock<TOutput> or ITargetBlock<TInput> interfaces directly or use the Encapsulate method to build a complex block that encapsulates the behavior of existing block types. Beispiele für die Implementierung benutzerdefinierter Datenflussblock-Funktionen finden Sie unter Exemplarische Vorgehensweise: Erstellen eines Datenflussblocktyps.For examples that show how to implement custom dataflow block functionality, see Walkthrough: Creating a Custom Dataflow Block Type.

[Nach oben][go to top]

TitelTitle BeschreibungDescription
Vorgehensweise: Schreiben und Lesen von Nachrichten in einem DatenflussblockHow to: Write Messages to and Read Messages from a Dataflow Block Veranschaulicht, wie Nachrichten in ein BufferBlock<T>-Objekt geschrieben und daraus gelesen werden.Demonstrates how to write messages to and read messages from a BufferBlock<T> object.
Vorgehensweise: Implementieren eines Producer-Consumer-MustersHow to: Implement a Producer-Consumer Dataflow Pattern Beschreibt, wie mit dem Datenflussmodell ein Producer-Consumer-Muster implementiert wird, bei dem der Producer Nachrichten an einen Datenflussblock sendet und der Consumer Nachrichten aus diesem Block liest.Describes how to use the dataflow model to implement a producer-consumer pattern, where the producer sends messages to a dataflow block, and the consumer reads messages from that block.
Vorgehensweise: Ausführen einer Aktion, wenn ein Datenflussblock Daten empfängtHow to: Perform Action When a Dataflow Block Receives Data Beschreibt, wie Delegaten für die Ausführungsdatenflussblocktypen ActionBlock<TInput>, TransformBlock<TInput,TOutput> und TransformManyBlock<TInput,TOutput> bereitgestellt werden.Describes how to provide delegates to the execution dataflow block types, ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput>.
Exemplarische Vorgehensweise: Erstellen einer DatenflusspipelineWalkthrough: Creating a Dataflow Pipeline Beschreibt, wie eine Datenflusspipeline erstellt wird, die Text aus dem Web herunterlädt und Vorgänge für diesen Text ausführt.Describes how to create a dataflow pipeline that downloads text from the web and performs operations on that text.
Vorgehensweise: Aufheben der Verknüpfungen von DatenflussblöckenHow to: Unlink Dataflow Blocks Veranschaulicht, wie mit der LinkTo-Methode die Verknüpfung zwischen einem Zielblock und der zugehörigen Quelle aufgelöst wird, nachdem die Quelle dem Ziel eine Nachricht anbietet.Demonstrates how to use the LinkTo method to unlink a target block from its source after the source offers a message to the target.
Exemplarische Vorgehensweise: Verwenden von Dataflow in einer Windows Forms-AnwendungWalkthrough: Using Dataflow in a Windows Forms Application Veranschaulicht, wie ein Netzwerk von Datenflussblöcken erstellt wird, die eine Bildverarbeitung in einer Windows Forms-Anwendung durchführen.Demonstrates how to create a network of dataflow blocks that perform image processing in a Windows Forms application.
Vorgehensweise: Abbrechen eines DatenflussblocksHow to: Cancel a Dataflow Block Veranschaulicht die Verwendung von Abbrüchen in einer Windows Forms-Anwendung.Demonstrates how to use cancellation in a Windows Forms application.
Vorgehensweise: Verwenden von JoinBlock zum Lesen aus mehreren QuellenHow to: Use JoinBlock to Read Data From Multiple Sources Erläutert die Verwendung der JoinBlock<T1,T2>-Klasse, um einen Vorgang durchzuführen, wenn Daten aus mehreren Quellen zur Verfügung stehen, sowie die Verwendung des nicht gierigen Modus, sodass mehrere Gruppierungsblöcke eine Datenquelle effizienter gemeinsam verwenden können.Explains how to use the JoinBlock<T1,T2> class to perform an operation when data is available from multiple sources, and how to use non-greedy mode to enable multiple join blocks to share a data source more efficiently.
Vorgehensweise: Festlegen des Parallelitätsgrads in einem DatenflussblockHow to: Specify the Degree of Parallelism in a Dataflow Block Beschreibt, wie die MaxDegreeOfParallelism-Eigenschaft festgelegt wird, damit ein Ausführungsdatenflussblock mehrere Nachrichten gleichzeitig verarbeiten kann.Describes how to set the MaxDegreeOfParallelism property to enable an execution dataflow block to process more than one message at a time.
Vorgehensweise: Angeben eines Taskplaners in einem DatenflussblockHow to: Specify a Task Scheduler in a Dataflow Block Veranschaulicht, wie ein bestimmter Aufgabenplaner zugeordnet wird, wenn Sie Datenfluss in Ihrer Anwendung verwenden.Demonstrates how to associate a specific task scheduler when you use dataflow in your application.
Exemplarische Vorgehensweise: Effizienzverbesserung durch Verwendung von BatchBlock und BatchedJoinBlockWalkthrough: Using BatchBlock and BatchedJoinBlock to Improve Efficiency Beschreibt, wie mit der BatchBlock<T>-Klasse die Effizienz von Datenbankeinfügevorgängen verbessert wird und wie mit der BatchedJoinBlock<T1,T2>-Klasse sowohl die Ergebnisse als auch Ausnahmen erfasst werden, die auftreten, während das Programm aus einer Datenbank liest.Describes how to use the BatchBlock<T> class to improve the efficiency of database insert operations, and how to use the BatchedJoinBlock<T1,T2> class to capture both the results and any exceptions that occur while the program reads from a database.
Exemplarische Vorgehensweise: Erstellen eines DatenflussblocktypsWalkthrough: Creating a Custom Dataflow Block Type Veranschaulicht zwei Möglichkeiten, einen Datenflussblocktyp zu erstellen, der benutzerdefiniertes Verhalten implementiert.Demonstrates two ways to create a dataflow block type that implements custom behavior.
Task Parallel Library (TPL)Task Parallel Library (TPL) Stellt die TPL vor, eine Bibliothek, die die parallele Programmierung in .NET Framework-Anwendungen vereinfacht.Introduces the TPL, a library that simplifies parallel and concurrent programming in .NET Framework applications.