Flux de données (bibliothèque parallèle de tâches)Dataflow (Task Parallel Library)

La bibliothèque parallèle de tâches (TPL) fournit des composants de flux de données destinés à augmenter la robustesse des applications prenant en charge l'accès concurrentiel.The Task Parallel Library (TPL) provides dataflow components to help increase the robustness of concurrency-enabled applications. Ces composants de flux de données sont regroupés sous le nom de bibliothèque de flux de données TPL.These dataflow components are collectively referred to as the TPL Dataflow Library. Ce modèle de flux de données favorise la programmation basée sur les acteurs en fournissant une transmission de messages in-process pour les flux de données à granularité grossière et les tâches de traitement "pipeline".This dataflow model promotes actor-based programming by providing in-process message passing for coarse-grained dataflow and pipelining tasks. Les composants de flux de données reposent sur les types et l'infrastructure de planification de la bibliothèque parallèle de tâches, et s'intègrent à la prise en charge des langages C#, Visual Basic et F# de la programmation asynchrone.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. Ces composants de flux de données sont utiles quand vous avez plusieurs opérations qui doivent communiquer entre elles de façon asynchrone ou quand vous voulez traiter les données à mesure qu'elles deviennent disponibles.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. Prenons par exemple une application qui traite les données d'image d'une webcam.For example, consider an application that processes image data from a web camera. En utilisant le modèle de flux de données, l'application peut traiter les trames d'images à mesure qu'elles deviennent disponibles.By using the dataflow model, the application can process image frames as they become available. Si l’application améliore les trames d’images, par exemple, en effectuant la correction de la lumière ou des yeux rouges, vous pouvez créer un pipeline de composants de flux de données.If the application enhances image frames, for example, by performing light correction or red-eye reduction, you can create a pipeline of dataflow components. Chaque étape du pipeline peut utiliser plusieurs fonctionnalités de parallélisme à granularité grossière, telles que les fonctionnalités fournies par la bibliothèque TPL qui permettent de transformer les images.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.

Ce document fournit une vue d'ensemble de la bibliothèque de flux de données TPL.This document provides an overview of the TPL Dataflow Library. Il décrit le modèle de programmation et les types de blocs de flux de données prédéfinis, et explique comment configurer des blocs de flux de données pour répondre aux besoins de vos applications.It describes the programming model, the predefined dataflow block types, and how to configure dataflow blocks to meet the specific requirements of your applications.

Notes

La bibliothèque de flux de données TPL (espace de noms System.Threading.Tasks.Dataflow) n'est pas distribuée avec .NET.The TPL Dataflow Library (the System.Threading.Tasks.Dataflow namespace) is not distributed with .NET. Pour installer l’espace de noms System.Threading.Tasks.Dataflow dans Visual Studio, ouvrez votre projet, choisissez Gérer les packages NuGet dans le menu Projet, puis recherchez en ligne le package System.Threading.Tasks.Dataflow.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. Vous pouvez également l’installer à l’aide de l’interface CLI .Net Core en exécutant dotnet add package System.Threading.Tasks.Dataflow.Alternatively, to install it using the .Net Core CLI, run dotnet add package System.Threading.Tasks.Dataflow.

Modèle de programmationProgramming Model

La bibliothèque de flux de données TPL constitue une base pour la transmission de messages et la parallélisation des applications nécessitant une utilisation importante du processeur et des E/S, et ayant un débit élevé et une faible latence.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. Elle permet également de contrôler explicitement la manière dont les données sont mises en mémoire tampon et se déplacent sur le système.It also gives you explicit control over how data is buffered and moves around the system. Pour mieux comprendre le modèle de programmation de flux de données, imaginez une application qui charge des images à partir du disque de manière asynchrone et crée un composite de ces images.To better understand the dataflow programming model, consider an application that asynchronously loads images from disk and creates a composite of those images. Les modèles de programmation traditionnels requièrent généralement l'utilisation de rappels et d'objets de synchronisation, tels que des verrous, pour coordonner les tâches et accéder aux données partagées.Traditional programming models typically require that you use callbacks and synchronization objects, such as locks, to coordinate tasks and access to shared data. À l'aide du modèle de programmation de flux de données, vous pouvez créer des objets de flux de données qui traitent les images à mesure qu'elles sont lues à partir du disque.By using the dataflow programming model, you can create dataflow objects that process images as they are read from disk. Sous le modèle de flux de données, vous déclarez la manière dont sont traitées les données quand elles deviennent disponibles, ainsi que les éventuelles dépendances qui existent entre les données.Under the dataflow model, you declare how data is handled when it becomes available, and also any dependencies between data. Le runtime gère les dépendances entre les données, ce qui vous évite d'avoir à synchroniser l'accès aux données partagées.Because the runtime manages dependencies between data, you can often avoid the requirement to synchronize access to shared data. De plus, étant donné que le runtime planifie les tâches en fonction de l'arrivée asynchrone des données, le flux de données peut améliorer la réactivité et le débit grâce à une gestion efficace des threads sous-jacents.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. Vous trouverez un exemple d’utilisation du modèle de programmation de flux de données pour implémenter le traitement d’image dans une application Windows Forms sur la page Procédure pas à pas : utiliser les flux de données dans une application Windows Forms.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.

Sources et ciblesSources and Targets

La bibliothèque de flux de données TPL comprend des blocs de flux de données, structures de données qui mettent les données en mémoire tampon et les traitent.The TPL Dataflow Library consists of dataflow blocks, which are data structures that buffer and process data. La bibliothèque parallèle de tâches définit trois types de blocs de flux de données : les blocs sources, les blocs cibles et les blocs propagateurs.The TPL defines three kinds of dataflow blocks: source blocks, target blocks, and propagator blocks. Un bloc source agit comme une source de données et peut donc être lu.A source block acts as a source of data and can be read from. Un bloc cible joue le rôle de récepteur de données, il est donc possible d'y écrire.A target block acts as a receiver of data and can be written to. Un bloc propagateur agit à la fois comme un bloc source et un bloc cible, et peut donc faire l'objet d'une lecture et d'une écriture.A propagator block acts as both a source block and a target block, and can be read from and written to. La bibliothèque parallèle de tâches définit l'interface System.Threading.Tasks.Dataflow.ISourceBlock<TOutput> pour représenter les sources, System.Threading.Tasks.Dataflow.ITargetBlock<TInput> pour représenter les cibles, et System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput,TOutput> pour représenter les propagateurs.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> hérite des deux ISourceBlock<TOutput> et de ITargetBlock<TInput>.IPropagatorBlock<TInput,TOutput> inherits from both ISourceBlock<TOutput>, and ITargetBlock<TInput>.

La bibliothèque de flux de données TPL fournit plusieurs types de blocs de flux de données prédéfinis qui implémentent les interfaces ISourceBlock<TOutput>, ITargetBlock<TInput> et IPropagatorBlock<TInput,TOutput>.The TPL Dataflow Library provides several predefined dataflow block types that implement the ISourceBlock<TOutput>, ITargetBlock<TInput>, and IPropagatorBlock<TInput,TOutput> interfaces. Ces types de blocs de flux de données sont décrits dans ce document dans la section Types de blocs de flux de données prédéfinis.These dataflow block types are described in this document in the section Predefined Dataflow Block Types.

Connexion des blocsConnecting Blocks

Vous pouvez aussi connecter des blocs de flux de données pour former des pipelines, qui sont des séquences linéaires de blocs de flux de données, ou bien des réseaux, qui sont des graphiques de blocs de flux de données.You can connect dataflow blocks to form pipelines, which are linear sequences of dataflow blocks, or networks, which are graphs of dataflow blocks. Un pipeline est une forme de réseau.A pipeline is one form of network. Dans un pipeline ou un réseau, les sources propagent des données de manière asynchrone vers les cibles à mesure que les données deviennent disponibles.In a pipeline or network, sources asynchronously propagate data to targets as that data becomes available. La méthode ISourceBlock<TOutput>.LinkTo lie un bloc de flux de données source à un bloc cible.The ISourceBlock<TOutput>.LinkTo method links a source dataflow block to a target block. Une source peut être liée à zéro, une ou plusieurs cibles. Une cible peut être liée à zéro, une ou plusieurs sources.A source can be linked to zero or more targets; targets can be linked from zero or more sources. Vous pouvez ajouter des blocs de flux de données à un pipeline ou en supprimer de manière simultanée.You can add or remove dataflow blocks to or from a pipeline or network concurrently. Les types de blocs de flux de données prédéfinis gèrent tous les aspects liés à la sécurité des threads pour les liaisons et les annulations de liaison.The predefined dataflow block types handle all thread-safety aspects of linking and unlinking.

Vous trouverez un exemple de connexion de blocs de flux de données permettant de former un pipeline de base sur la page Procédure pas à pas : créer un pipeline de flux de données.For an example that connects dataflow blocks to form a basic pipeline, see Walkthrough: Creating a Dataflow Pipeline. Vous trouverez un exemple de connexion de blocs de flux de données permettant de former un réseau plus complexe sur la page Procédure pas à pas : utiliser les flux de données dans une application Windows Forms.For an example that connects dataflow blocks to form a more complex network, see Walkthrough: Using Dataflow in a Windows Forms Application. Vous trouverez un exemple de dissociation d’une cible et d’une source après que la source a envoyé un message à la cible sur la page Guide pratique : dissocier des blocs de flux de données.For an example that unlinks a target from a source after the source offers the target a message, see How to: Unlink Dataflow Blocks.

FiltrageFiltering

Quand vous appelez la méthode ISourceBlock<TOutput>.LinkTo pour lier une source à une cible, vous pouvez fournir un délégué qui détermine si le bloc cible accepte ou rejette les messages en fonction de la valeur de ce message.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. Ce mécanisme de filtrage permet de garantir qu'un bloc de flux de données recevra uniquement certaines valeurs.This filtering mechanism is a useful way to guarantee that a dataflow block receives only certain values. Pour la plupart des types de blocs de flux de données prédéfinis, si un bloc source est connecté à plusieurs blocs cibles, quand un bloc cible rejette un message, la source envoie le message à la cible suivante.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. L'ordre dans lequel une source envoie des messages aux cibles est défini par la source et peut varier en fonction du type de la source.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. La plupart des types de blocs sources arrêtent d'envoyer un message une fois celui-ci accepté par une cible.Most source block types stop offering a message after one target accepts that message. La classe BroadcastBlock<T> est une exception. En effet, celle-ci envoie chaque message à l'ensemble des cibles, même si celles-ci le rejettent.One exception to this rule is the BroadcastBlock<T> class, which offers each message to all targets, even if some targets reject the message. Vous trouverez un exemple d’utilisation du filtrage permettant de traiter uniquement certains messages sur la page Procédure pas à pas : utiliser les flux de données dans une application Windows Forms.For an example that uses filtering to process only certain messages, see Walkthrough: Using Dataflow in a Windows Forms Application.

Important

Étant donné que chaque type de bloc de flux de données source prédéfini garantit la propagation des messages dans l'ordre où ils sont reçus, tous les messages doivent être lus depuis le bloc source avant que celui-ci ne puisse traiter le message suivant.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. Par conséquent, quand vous utilisez le filtrage pour connecter plusieurs cibles à une source, assurez-vous que chaque message soit reçu par au moins un bloc cible.Therefore, when you use filtering to connect multiple targets to a source, make sure that at least one target block receives each message. Sinon, votre application peut se bloquer.Otherwise, your application might deadlock.

Transmission de messagesMessage Passing

Le modèle de programmation de flux de données est lié au concept de transmission de messages, durant laquelle les composants indépendants d’un programme communiquent entre eux à l’aide de messages.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. Pour propager des messages entre composants d'application, vous pouvez appeler les méthodes Post et DataflowBlock.SendAsync afin d’envoyer des messages aux blocs de flux de données cibles (Post agit de façon synchrone et SendAsync de façon asynchrone), et les méthodes Receive, ReceiveAsync et TryReceive afin de recevoir des messages provenant de blocs sources.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. Vous pouvez combiner ces méthodes à des pipelines ou réseaux de flux de données en envoyant des données d'entrée au nœud principal (bloc cible) et en recevant des données de sortie de la part du nœud terminal du pipeline ou des nœuds terminaux du réseau (un ou plusieurs blocs sources).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). Vous pouvez également utiliser la méthode Choose pour lire la première des sources fournies qui contient des données et effectuer des actions sur ces données.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.

Les blocs sources envoient des données aux blocs cibles en appelant la méthode ITargetBlock<TInput>.OfferMessage.Source blocks offer data to target blocks by calling the ITargetBlock<TInput>.OfferMessage method. Le bloc cible peut répondre à un message envoyé de trois manières : il peut accepter le message, le refuser ou le différer.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. Quand la cible accepte le message, la méthode OfferMessage retourne Accepted.When the target accepts the message, the OfferMessage method returns Accepted. Quand la cible refuse le message, la méthode OfferMessage retourne Declined.When the target declines the message, the OfferMessage method returns Declined. Quand la cible décide de ne plus recevoir de messages de la source, OfferMessage renvoie DecliningPermanently.When the target requires that it no longer receives any messages from the source, OfferMessage returns DecliningPermanently. Les types de blocs sources prédéfinis n'envoient plus de messages aux cibles liées après réception d'une telle valeur et sont automatiquement dissociés de ces cibles.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.

Quand un bloc cible diffère le message pour une utilisation ultérieure, la méthode OfferMessage retourne Postponed.When a target block postpones the message for later use, the OfferMessage method returns Postponed. Un bloc cible qui diffère un message peut appeler par la suite la méthode ISourceBlock<TOutput>.ReserveMessage pour tenter de réserver le message envoyé.A target block that postpones a message can later call the ISourceBlock<TOutput>.ReserveMessage method to try to reserve the offered message. À ce stade, soit le message est toujours disponible et peut être utilisé par le bloc cible, soit le message a été utilisé par une autre cible.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. Si, par la suite, le bloc cible demande le message ou n'en a plus besoin, il appellera respectivement la méthode ISourceBlock<TOutput>.ConsumeMessage ou la méthode ReleaseReservation.When the target block later requires the message or no longer needs the message, it calls the ISourceBlock<TOutput>.ConsumeMessage or ReleaseReservation method, respectively. La réservation de messages est généralement utilisée par les types de blocs de flux de données qui fonctionnent en mode non gourmand.Message reservation is typically used by the dataflow block types that operate in non-greedy mode. Le mode non gourmand est expliqué plus loin dans ce document.Non-greedy mode is explained later in this document. Plutôt que de réserver un message différé, un bloc cible peut également utiliser la méthode ISourceBlock<TOutput>.ConsumeMessage pour tenter d'utiliser directement le message différé.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.

Achèvement des blocs de flux de donnéesDataflow Block Completion

Les blocs de flux de données prennent également en charge le concept d’achèvement.Dataflow blocks also support the concept of completion. Un bloc de flux de données qui est achevé n'effectue plus aucune tâche.A dataflow block that is in the completed state does not perform any further work. Chaque bloc de flux de données est associé à un objet System.Threading.Tasks.Task, appelé tâche d'achèvement, qui représente l'état d'achèvement du bloc.Each dataflow block has an associated System.Threading.Tasks.Task object, known as a completion task, that represents the completion status of the block. Étant donné que vous pouvez attendre qu'un objet Task soit terminé, vous pouvez, à l'aide de tâches d'achèvement, attendre l'achèvement d'un ou plusieurs nœuds terminaux d'un réseau de flux de données.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. L'interface IDataflowBlock définit la méthode Complete qui informe le bloc de flux de données qu'une requête exige son achèvement, ainsi que la propriété Completion qui retourne la tâche d'achèvement pour le bloc de flux de données.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> et ITargetBlock<TInput> héritent de l'interface IDataflowBlock.Both ISourceBlock<TOutput> and ITargetBlock<TInput> inherit the IDataflowBlock interface.

Il existe deux façons de déterminer si un bloc de flux de données s'est terminé sans erreur, si une ou plusieurs erreurs se sont produites ou s'il a été annulé.There are two ways to determine whether a dataflow block completed without error, encountered one or more errors, or was canceled. La première consiste à appeler la méthode Task.Wait sur la tâche d'achèvement dans un bloc try-catch (Try-Catch en Visual Basic).The first way is to call the Task.Wait method on the completion task in a try-catch block (Try-Catch in Visual Basic). Dans l'exemple suivant, un ActionBlock<TInput> objet lève une exception ArgumentOutOfRangeException si sa valeur d'entrée est inférieure à zéro.The following example creates an ActionBlock<TInput> object that throws ArgumentOutOfRangeException if its input value is less than zero. L’exception AggregateException est levée quand cet exemple appelle Wait sur la tâche d’achèvement.AggregateException is thrown when this example calls Wait on the completion task. ArgumentOutOfRangeException est accessible via la propriété InnerExceptions de l'objet AggregateException.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.
'         

Dans cet exemple, une exception n'est pas gérée dans le délégué d'un bloc de flux de données d'exécution.This example demonstrates the case in which an exception goes unhandled in the delegate of an execution dataflow block. Nous vous recommandons de gérer les exceptions dans le corps des blocs.We recommend that you handle exceptions in the bodies of such blocks. Toutefois, si vous ne parvenez pas à le faire, le bloc se comportera comme s'il avait été annulé et ne traitera pas les messages entrants.However, if you are unable to do so, the block behaves as though it was canceled and does not process incoming messages.

Quand un bloc de flux de données est annulé de manière explicite, l'objet AggregateException contient OperationCanceledException dans la propriété InnerExceptions.When a dataflow block is canceled explicitly, the AggregateException object contains OperationCanceledException in the InnerExceptions property. Pour plus d’informations sur l’annulation de flux de données, consultez la section Permettre les annulations.For more information about dataflow cancellation, see Enabling Cancellation section.

La deuxième méthode permettant de déterminer l’état d’achèvement d’un bloc de flux de données est d’utiliser une continuation de la tâche d’achèvement, ou d’utiliser les fonctionnalités de langage asynchrones de C# et de Visual Basic pour attendre la tâche d’achèvement de manière asynchrone.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. Le délégué que vous fournissez à la méthode Task.ContinueWith prend un objet Task qui représente la tâche précédente.The delegate that you provide to the Task.ContinueWith method takes a Task object that represents the antecedent task. Dans le cas de la propriété Completion, le délégué de la continuation prend la tâche d'achèvement.In the case of the Completion property, the delegate for the continuation takes the completion task itself. L’exemple suivant ressemble au précédent, mais il utilise également la méthode ContinueWith pour créer une tâche de continuation qui imprime l’état de l’opération globale de flux de données.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.
'         

Vous pouvez également utiliser des propriétés telles que IsCanceled dans le corps de la tâche de continuation pour obtenir des informations supplémentaires sur l'état d'achèvement d'un bloc de flux de données.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. Pour plus d’informations sur les tâches de continuation et leur rôle dans les annulations et la gestion des erreurs, consultez Chaînage des tâches à l’aide de tâches de continuation, Annulation de tâches et Gestion des exceptions.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.

Types de blocs de flux de données prédéfinisPredefined Dataflow Block Types

La bibliothèque de flux de données TPL fournit plusieurs types de blocs de flux de données prédéfinis.The TPL Dataflow Library provides several predefined dataflow block types. Ces types sont répartis en trois catégories : blocs de mise en mémoire tampon, blocs d’exécution et blocs de regroupement.These types are divided into three categories: buffering blocks, execution blocks, and grouping blocks. Les sections suivantes décrivent les types de blocs qui composent ces catégories.The following sections describe the block types that make up these categories.

Blocs de mise en mémoire tamponBuffering Blocks

Les blocs de mise en mémoire tampon contiennent des données destinées aux consommateurs de données.Buffering blocks hold data for use by data consumers. La bibliothèque de flux de données TPL fournit trois types de blocs de mise en mémoire tampon : System.Threading.Tasks.Dataflow.BufferBlock<T>, System.Threading.Tasks.Dataflow.BroadcastBlock<T> et 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)

La classe BufferBlock<T> représente une structure de messagerie asynchrone à usage général.The BufferBlock<T> class represents a general-purpose asynchronous messaging structure. Cette classe stocke une file d'attente de messages de type premier entré, premier sorti (FIFO). Plusieurs cibles peuvent lire ces messages et plusieurs sources peuvent y écrire.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. Quand une cible reçoit un message d'un objet BufferBlock<T>, ce message est supprimé de la file d'attente.When a target receives a message from a BufferBlock<T> object, that message is removed from the message queue. Par conséquent, même si un objet BufferBlock<T> peut avoir plusieurs cibles, seule une cible reçoit chaque message.Therefore, although a BufferBlock<T> object can have multiple targets, only one target will receive each message. La classe BufferBlock<T> est utile quand vous voulez transmettre plusieurs messages à un autre composant et que ce composant doit recevoir chaque message.The BufferBlock<T> class is useful when you want to pass multiple messages to another component, and that component must receive each message.

Dans l'exemple simple qui suit, plusieurs valeurs Int32 sont publiées sur un objet BufferBlock<T>, puis sont lues depuis l'objet.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
'          

Vous trouverez un exemple complet montrant comment écrire et lire des messages dans un objet BufferBlock<T> sur la page Guide pratique : écrire et lire des messages dans un bloc de flux de données.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)

La classe BroadcastBlock<T> est utile quand vous devez transmettre plusieurs messages à un autre composant, mais que ce composant nécessite uniquement la valeur la plus récente.The BroadcastBlock<T> class is useful when you must pass multiple messages to another component, but that component needs only the most recent value. Cette classe est également utile quand vous voulez diffuser un message vers plusieurs composants.This class is also useful when you want to broadcast a message to multiple components.

Dans l'exemple simple qui suit, une valeur Double est publiée sur un objet BroadcastBlock<T>, puis est lue plusieurs fois depuis l'objet.The following basic example posts a Double value to a BroadcastBlock<T> object and then reads that value back from that object several times. Étant donné que les valeurs ne sont pas supprimées des objets BroadcastBlock<T> après leur lecture, la même valeur est disponible à chaque fois.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
'          

Vous trouverez un exemple complet montrant comment utiliser BroadcastBlock<T> pour diffuser un message vers plusieurs blocs cibles sur la page Guide pratique : spécifier un Planificateur de tâches dans un bloc de flux de données.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)

La classe WriteOnceBlock<T> est similaire à la classe BroadcastBlock<T>, à ceci près qu'il n'est possible d'écrire qu'une seule fois dans un objet WriteOnceBlock<T>.The WriteOnceBlock<T> class resembles the BroadcastBlock<T> class, except that a WriteOnceBlock<T> object can be written to one time only. Vous pouvez assimiler WriteOnceBlock<T> au mot clé readonly en C# (ReadOnly en Visual Basic). Toutefois, la différence se trouve dans le fait qu'un objet WriteOnceBlock<T> devient immuable après avoir reçu une valeur, et non à la construction.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. Comme pour la classe BroadcastBlock<T>, quand une cible reçoit un message d'un objet WriteOnceBlock<T>, le message n'est pas supprimé de l'objet.Like the BroadcastBlock<T> class, when a target receives a message from a WriteOnceBlock<T> object, that message is not removed from that object. Par conséquent, plusieurs cibles reçoivent une copie du message.Therefore, multiple targets receive a copy of the message. La classe WriteOnceBlock<T> est utile quand vous voulez propager uniquement le premier d'une liste de messages.The WriteOnceBlock<T> class is useful when you want to propagate only the first of multiple messages.

Dans l'exemple simple qui suit, plusieurs valeurs String sont publiées sur un objet WriteOnceBlock<T>, puis sont lues depuis l'objet.The following basic example posts multiple String values to a WriteOnceBlock<T> object and then reads the value back from that object. Étant donné qu'il n'est possible d'écrire dans un objet WriteOnceBlock<T> qu'une seule fois, une fois qu'un objet WriteOnceBlock<T> reçoit un message, il rejette les messages suivants.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
'          

Vous trouverez un exemple complet montrant comment utiliser WriteOnceBlock<T> pour recevoir la valeur de la première opération terminée sur la page Guide pratique : dissocier des blocs de flux de données.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.

Blocs d'exécutionExecution Blocks

Les blocs d'exécution appellent un délégué fourni par l'utilisateur pour chaque donnée reçue.Execution blocks call a user-provided delegate for each piece of received data. La bibliothèque de flux de données TPL fournit trois types de blocs d'exécution : ActionBlock<TInput>, System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput> et 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)

La classe ActionBlock<TInput> est un bloc cible qui appelle un délégué quand il reçoit des données.The ActionBlock<TInput> class is a target block that calls a delegate when it receives data. Imaginez un objet ActionBlock<TInput> utilisé comme un délégué qui s'exécute de façon asynchrone quand des données deviennent disponibles.Think of a ActionBlock<TInput> object as a delegate that runs asynchronously when data becomes available. Le délégué que vous fournissez à un objet ActionBlock<TInput> peut être de type Action<T> ou System.Func<TInput, Task>.The delegate that you provide to an ActionBlock<TInput> object can be of type Action<T> or type System.Func<TInput, Task>. Quand vous utilisez un objet ActionBlock<TInput> avec Action<T>, le traitement de chaque élément d'entrée est considéré comme terminé quand le délégué est retourné.When you use an ActionBlock<TInput> object with Action<T>, processing of each input element is considered completed when the delegate returns. Quand vous utilisez un objet ActionBlock<TInput> avec System.Func<TInput, Task>, le traitement de chaque élément d'entrée n'est considéré comme terminé que quand l'objet Task retourné est à l'état achevé.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. À l'aide de ces deux mécanismes, vous pouvez utiliser ActionBlock<TInput> pour le traitement synchrone et asynchrone de chaque élément d'entrée.By using these two mechanisms, you can use ActionBlock<TInput> for both synchronous and asynchronous processing of each input element.

Dans l'exemple simple qui suit, plusieurs valeurs Int32 sont publiées sur un objet ActionBlock<TInput>.The following basic example posts multiple Int32 values to an ActionBlock<TInput> object. L'objet ActionBlock<TInput> imprime ces valeurs dans la console.The ActionBlock<TInput> object prints those values to the console. Cet exemple attribue ensuite au bloc l'état achevé, puis attend que toutes les tâches de flux de données soient terminées.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
'          

Vous trouverez des exemples complets montrant comment utiliser des délégués avec la classe ActionBlock<TInput> sur la page Guide pratique : exécuter des actions lorsqu'un bloc de flux de données reçoit des données.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)

La classe TransformBlock<TInput,TOutput> est similaire à la classe ActionBlock<TInput>, à ceci près qu'elle joue à la fois le rôle de source et le rôle de cible.The TransformBlock<TInput,TOutput> class resembles the ActionBlock<TInput> class, except that it acts as both a source and as a target. Le délégué que vous passez à un objet TransformBlock<TInput,TOutput> renvoie une valeur de type TOutput.The delegate that you pass to a TransformBlock<TInput,TOutput> object returns a value of type TOutput. Le délégué que vous fournissez à un objet TransformBlock<TInput,TOutput> peut être de type System.Func<TInput, TOutput> ou System.Func<TInput, Task<TOutput>>.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>>. Quand vous utilisez un objet TransformBlock<TInput,TOutput> avec System.Func<TInput, TOutput>, le traitement de chaque élément d'entrée est considéré comme terminé quand le délégué est retourné.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. Quand vous utilisez un objet TransformBlock<TInput,TOutput> utilisé avec System.Func<TInput, Task<TOutput>>, le traitement de chaque élément d'entrée n'est considéré comme terminé que quand l'objet Task<TResult> retourné est à l'état achevé.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. Comme pour ActionBlock<TInput>, ces deux mécanismes vous permettent d'utiliser TransformBlock<TInput,TOutput> pour le traitement synchrone et asynchrone de chaque élément d'entrée.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.

Dans l'exemple simple qui suit, l'objet TransformBlock<TInput,TOutput> créé calcule la racine carrée de son entrée.The following basic example creates a TransformBlock<TInput,TOutput> object that computes the square root of its input. L'objet TransformBlock<TInput,TOutput> prend des valeurs Int32 comme entrée et produit des valeurs Double comme sortie.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
'          

Vous trouverez des exemples complets utilisant TransformBlock<TInput,TOutput> dans un réseau de blocs de flux de données qui réalise un traitement d’image dans une application Windows Forms sur la page Procédure pas à pas : utiliser un flux de données dans une application Windows Forms.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)

La classe TransformManyBlock<TInput,TOutput> est similaire à la classe TransformBlock<TInput,TOutput>, à ceci près que TransformManyBlock<TInput,TOutput> produit zéro, une ou plusieurs valeurs de sortie pour chaque valeur d'entrée, au lieu d'une seule valeur de sortie pour chaque valeur d'entrée.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. Le délégué que vous fournissez à un objet TransformManyBlock<TInput,TOutput> peut être de type System.Func<TInput, IEnumerable<TOutput>> ou System.Func<TInput, Task<IEnumerable<TOutput>>>.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>>>. Quand vous utilisez un objet TransformManyBlock<TInput,TOutput> avec System.Func<TInput, IEnumerable<TOutput>>, le traitement de chaque élément d'entrée est considéré comme terminé quand le délégué est retourné.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. Quand vous utilisez un objet TransformManyBlock<TInput,TOutput> avec System.Func<TInput, Task<IEnumerable<TOutput>>>, le traitement de chaque élément d'entrée n'est considéré comme terminé que quand l'objet System.Threading.Tasks.Task<IEnumerable<TOutput>> retourné est à l'état achevé.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.

Dans l'exemple simple qui suit, l'objet TransformManyBlock<TInput,TOutput> créé fractionne les chaînes en séquences de caractères.The following basic example creates a TransformManyBlock<TInput,TOutput> object that splits strings into their individual character sequences. L'objet TransformManyBlock<TInput,TOutput> prend des valeurs String comme entrée et produit des valeurs Char comme sortie.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
'          

Vous trouverez des exemples complets utilisant TransformManyBlock<TInput,TOutput> pour produire plusieurs sorties indépendantes pour chaque entrée dans un pipeline de flux de données sur la page Procédure pas à pas : créer un pipeline de flux de données.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.

Degré de parallélismeDegree of Parallelism

Chaque objet ActionBlock<TInput>, TransformBlock<TInput,TOutput> et TransformManyBlock<TInput,TOutput> met en mémoire tampon les messages entrants jusqu'à ce que le bloc soit prêt à les traiter.Every ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput> object buffers input messages until the block is ready to process them. Par défaut, ces classes de traitent les messages un par un, dans l'ordre dans lequel ils sont reçus.By default, these classes process messages in the order in which they are received, one message at a time. Vous pouvez également spécifier le degré de parallélisme permettant aux objets ActionBlock<TInput>, TransformBlock<TInput,TOutput> et TransformManyBlock<TInput,TOutput> de traiter plusieurs messages simultanément.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. Pour plus d'informations sur l'exécution simultanée, consultez la section "Spécification du degré de parallélisme" plus loin dans ce document.For more information about concurrent execution, see the section Specifying the Degree of Parallelism later in this document. Vous trouverez un exemple dans lequel un degré de parallélisme est défini pour permettre à un bloc de flux de données d’exécution de traiter plusieurs messages à la fois sur la page Guide pratique : spécifier le degré de parallélisme dans un bloc de flux de données.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.

Récapitulation des types déléguésSummary of Delegate Types

Le tableau suivant récapitule les types délégués que vous pouvez fournir aux objets ActionBlock<TInput>, TransformBlock<TInput,TOutput> et TransformManyBlock<TInput,TOutput>.The following table summarizes the delegate types that you can provide to ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput> objects. Le tableau indique également si le type délégué fonctionne de façon synchrone ou asynchrone.This table also specifies whether the delegate type operates synchronously or asynchronously.

TapezType Type délégué synchroneSynchronous Delegate Type Type délégué asynchroneAsynchronous 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>>>

Vous pouvez également utiliser des expressions lambda quand vous utilisez des types de blocs d'exécution.You can also use lambda expressions when you work with execution block types. Vous trouverez un exemple qui montre comment utiliser une expression lambda avec un bloc d’exécution sur la page Guide pratique : exécuter des actions lorsqu’un bloc de flux de données reçoit des données.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.

Blocs de regroupementGrouping Blocks

Les blocs de regroupement combinent les données d'une ou plusieurs sources, sous diverses contraintes.Grouping blocks combine data from one or more sources and under various constraints. La bibliothèque de flux de données TPL fournit trois types de blocs de regroupement : BatchBlock<T>, JoinBlock<T1,T2> et 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)

La classe BatchBlock<T> combine des jeux de données d'entrée (ou lots), dans des tableaux de données de sortie.The BatchBlock<T> class combines sets of input data, which are known as batches, into arrays of output data. Vous spécifiez la taille de chaque lot quand vous créez un objet BatchBlock<T>.You specify the size of each batch when you create a BatchBlock<T> object. Quand l'objet BatchBlock<T> reçoit le nombre spécifié d'éléments d'entrée, il propage de manière asynchrone un tableau contenant ces éléments.When the BatchBlock<T> object receives the specified count of input elements, it asynchronously propagates out an array that contains those elements. Si un objet BatchBlock<T> est à l'état achevé, mais ne contient pas suffisamment d'éléments pour former un lot, il propage un tableau final contenant les éléments d'entrée restants.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.

La classe BatchBlock<T> peut fonctionner en mode gourmand ou non gourmand.The BatchBlock<T> class operates in either greedy or non-greedy mode. En mode gourmand, qui est le mode par défaut, un objet BatchBlock<T> accepte tous les messages qui lui sont envoyés et propage un tableau après avoir reçu le nombre spécifié d'éléments.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. En mode non gourmand, un objet BatchBlock<T> diffère tous les messages entrants jusqu'à ce que suffisamment de sources aient envoyé au bloc un nombre de messages permettant de former un lot.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. Le mode gourmand est généralement plus performant que le mode non gourmand, car il nécessite une charge de traitement moindre.Greedy mode typically performs better than non-greedy mode because it requires less processing overhead. Toutefois, vous pouvez utiliser le mode non gourmand quand vous devez coordonner la consommation de plusieurs sources de façon atomique.However, you can use non-greedy mode when you must coordinate consumption from multiple sources in an atomic fashion. Pour spécifier le mode non gourmand, définissez Greedy sur False dans le paramètre dataflowBlockOptions du constructeur BatchBlock<T>.Specify non-greedy mode by setting Greedy to False in the dataflowBlockOptions parameter in the BatchBlock<T> constructor.

Dans l'exemple simple qui suit, plusieurs valeurs Int32 sont publiées sur un objet BatchBlock<T> qui contient un lot de dix éléments.The following basic example posts several Int32 values to a BatchBlock<T> object that holds ten elements in a batch. Pour garantir que toutes les valeurs de BatchBlock<T> soient propagées, cet exemple appelle la méthode Complete.To guarantee that all values propagate out of the BatchBlock<T>, this example calls the Complete method. La méthode Complete définit l'objet BatchBlock<T> sur l'état achevé. L'objet BatchBlock<T> propage donc les éléments restants dans un dernier lot.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.
'          

Vous trouverez un exemple complet utilisant BatchBlock<T> pour améliorer l'efficacité des opérations d'insertion en base de données sur la page Procédure pas à pas : utiliser BatchBlock et BatchedJoinBlock pour améliorer l'efficacité.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, ...)

Les classes JoinBlock<T1,T2> et JoinBlock<T1,T2,T3> collectent des éléments d'entrée et propagent les objets System.Tuple<T1,T2> ou System.Tuple<T1,T2,T3> qui contiennent ces éléments.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. Les classes JoinBlock<T1,T2> et JoinBlock<T1,T2,T3> n'héritent pas de ITargetBlock<TInput>.The JoinBlock<T1,T2> and JoinBlock<T1,T2,T3> classes do not inherit from ITargetBlock<TInput>. Au lieu de cela, elles fournissent les propriétés Target1, Target2 et Target3 qui implémentent ITargetBlock<TInput>.Instead, they provide properties, Target1, Target2, and Target3, that implement ITargetBlock<TInput>.

Comme BatchBlock<T>, JoinBlock<T1,T2> et JoinBlock<T1,T2,T3> peuvent fonctionner en mode gourmand ou non gourmand.Like BatchBlock<T>, JoinBlock<T1,T2> and JoinBlock<T1,T2,T3> operate in either greedy or non-greedy mode. En mode gourmand, qui est le mode par défaut, un objet JoinBlock<T1,T2> ou JoinBlock<T1,T2,T3> accepte tous les messages qui lui sont envoyés et propage un tuple chaque fois que l'une de ses cibles reçoit au moins un message.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. En mode non gourmand, un objet JoinBlock<T1,T2> ou JoinBlock<T1,T2,T3> diffère tous les messages entrants jusqu'à ce que toutes les cibles aient reçu les données requises pour créer un tuple.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. À ce stade, le bloc s'engage dans un protocole de validation en deux phases pour récupérer atomiquement tous les éléments requis à partir des sources.At this point, the block engages in a two-phase commit protocol to atomically retrieve all required items from the sources. Ce report permet à une autre entité de consommer les données pendant ce temps, pour que l'ensemble du système puisse progresser.This postponement makes it possible for another entity to consume the data in the meantime, to allow the overall system to make forward progress.

Dans l'exemple simple qui suit, un objet JoinBlock<T1,T2,T3> nécessite plusieurs données pour calculer une valeur.The following basic example demonstrates a case in which a JoinBlock<T1,T2,T3> object requires multiple data to compute a value. Dans cet exemple, l'objet JoinBlock<T1,T2,T3> créé nécessite deux valeurs Int32 et une valeur Char pour effectuer une opération arithmétique.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
'          

Vous trouverez un exemple complet utilisant des objets JoinBlock<T1,T2> en mode non gourmand pour partager une ressource de manière coopérative sur la page Guide pratique : utiliser JoinBlock pour lire des données issues de plusieurs sources.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, ...)

Les classes BatchedJoinBlock<T1,T2> et BatchedJoinBlock<T1,T2,T3> collectent des lots d'éléments d'entrée et propagent les objets System.Tuple(IList(T1), IList(T2)) ou System.Tuple(IList(T1), IList(T2), IList(T3)) qui contiennent ces éléments.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. BatchedJoinBlock<T1,T2> est un mélange entre BatchBlock<T> et JoinBlock<T1,T2>.Think of BatchedJoinBlock<T1,T2> as a combination of BatchBlock<T> and JoinBlock<T1,T2>. Vous spécifiez la taille de chaque lot quand vous créez un objet BatchedJoinBlock<T1,T2>.Specify the size of each batch when you create a BatchedJoinBlock<T1,T2> object. BatchedJoinBlock<T1,T2> fournit également les propriétés Target1 et Target2 qui implémentent ITargetBlock<TInput>.BatchedJoinBlock<T1,T2> also provides properties, Target1 and Target2, that implement ITargetBlock<TInput>. Quand le nombre spécifié d'éléments d'entrée est reçu par l'ensemble des cibles, l'objet BatchedJoinBlock<T1,T2> propage de manière asynchrone un objet System.Tuple(IList(T1), IList(T2)) qui contient ces éléments.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.

Dans l'exemple simple qui suit, l'objet BatchedJoinBlock<T1,T2> créé contient des résultats, des valeurs Int32 et des erreurs qui sont des objets Exception.The following basic example creates a BatchedJoinBlock<T1,T2> object that holds results, Int32 values, and errors that are Exception objects. Dans cet exemple, plusieurs opérations sont effectuées. Les résultats sont écrits dans la propriété Target1 et les erreurs dans la propriété Target2 de l'objet BatchedJoinBlock<T1,T2>.This example performs multiple operations and writes results to the Target1 property, and errors to the Target2 property, of the BatchedJoinBlock<T1,T2> object. Étant donné que le nombre d'opérations ayant réussi et ayant échoué n'est pas connu à l'avance, les objets IList<T> permettent à chaque cible de recevoir zéro, une ou plusieurs valeurs.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.
'          

Vous trouverez un exemple complet utilisant BatchedJoinBlock<T1,T2> pour capturer les résultats et toutes les exceptions qui se produisent quand le programme lit les données d'une base de données sur la page Procédure pas à pas : utiliser BatchBlock et BatchedJoinBlock pour améliorer l'efficacité.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.

Configuration du comportement des blocs de flux de donnéesConfiguring Dataflow Block Behavior

Vous pouvez activer des options supplémentaires en fournissant un objet System.Threading.Tasks.Dataflow.DataflowBlockOptions au constructeur de types de blocs de flux de données.You can enable additional options by providing a System.Threading.Tasks.Dataflow.DataflowBlockOptions object to the constructor of dataflow block types. Ces options permettent de contrôler le comportement, comme celui du planificateur qui gère la tâche sous-jacente et le degré de parallélisme.These options control behavior such the scheduler that manages the underlying task and the degree of parallelism. DataflowBlockOptions possède également des types dérivés qui spécifient le comportement spécifique à certains types de blocs de flux de données.The DataflowBlockOptions also has derived types that specify behavior that is specific to certain dataflow block types. Le tableau suivant récapitule les types d'options qui sont associés à chaque type de bloc de flux de données.The following table summarizes which options type is associated with each dataflow block type.

Type de bloc de flux de donnéesDataflow Block Type Type DataflowBlockOptionsDataflowBlockOptions 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

Les sections suivantes fournissent des informations supplémentaires sur les types importants d'options de blocs de flux de données qui sont disponibles via les classes System.Threading.Tasks.Dataflow.DataflowBlockOptions, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions et System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions.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.

Spécification du planificateur de tâchesSpecifying the Task Scheduler

Chaque bloc de flux de données prédéfini utilise le mécanisme de planification des tâches TPL pour effectuer des activités, telles que la propagation de données vers une cible, la réception de données à partir d'une source et l'exécution de délégués définis par l'utilisateur quand des données deviennent disponibles.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 est une classe abstraite qui représente un planificateur de tâches qui place des tâches en attente dans des threads.TaskScheduler is an abstract class that represents a task scheduler that queues tasks onto threads. Le planificateur de tâches par défaut, Default, utilise la classe ThreadPool pour placer des tâches en file d’attente et les exécuter.The default task scheduler, Default, uses the ThreadPool class to queue and execute work. Vous pouvez remplacer le planificateur de tâches par défaut en définissant la propriété TaskScheduler quand vous créez un objet de bloc de flux de données.You can override the default task scheduler by setting the TaskScheduler property when you construct a dataflow block object.

Quand un même planificateur de tâches gère plusieurs blocs de flux de données, il peut appliquer les mêmes stratégies à chacune d'elles.When the same task scheduler manages multiple dataflow blocks, it can enforce policies across them. Par exemple, si plusieurs blocs de flux de données sont configurés de manière à cibler le planificateur exclusif du même objet ConcurrentExclusiveSchedulerPair, toutes les tâches qui sont exécutées dans ces blocs seront sérialisées.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. De même, si ces blocs sont configurés de manière à cibler le planificateur simultané du même objet ConcurrentExclusiveSchedulerPair et que le planificateur est configuré avec un niveau d'accès concurrentiel maximal, toutes les tâches de ces blocs seront limitées au nombre d'opérations simultanées.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. Vous trouverez un exemple utilisant la classe ConcurrentExclusiveSchedulerPair pour permettre que des opérations de lecture s’effectuent en parallèle, tout en imposant que chaque opération d’écriture soit réalisée de manière exclusive sur la page Guide pratique : spécifier un Planificateur de tâches dans un bloc de flux de données.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. Pour plus d’informations sur les planificateurs de tâches dans la bibliothèque parallèle de tâches, consultez la rubrique sur la classe TaskScheduler.For more information about task schedulers in the TPL, see the TaskScheduler class topic.

Spécification du degré de parallélismeSpecifying the Degree of Parallelism

Par défaut, les trois types de blocs d'exécution fournis par la bibliothèque de flux de données TPL (ActionBlock<TInput>, TransformBlock<TInput,TOutput> et TransformManyBlock<TInput,TOutput>) traitent les messages un par un.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. Ces types de blocs de flux de données traitent également les messages dans l'ordre dans lequel ils sont reçus.These dataflow block types also process messages in the order in which they are received. Pour permettre aux blocs de flux de données de traiter simultanément les messages, définissez la propriété ExecutionDataflowBlockOptions.MaxDegreeOfParallelism au moment de créer l'objet de bloc de flux de données.To enable these dataflow blocks to process messages concurrently, set the ExecutionDataflowBlockOptions.MaxDegreeOfParallelism property when you construct the dataflow block object.

La valeur par défaut de MaxDegreeOfParallelism est 1, ce qui signifie que le bloc de flux de données traitera les messages un par un.The default value of MaxDegreeOfParallelism is 1, which guarantees that the dataflow block processes one message at a time. En définissant cette propriété sur une valeur supérieure à 1, vous permettez au bloc de flux de données de traiter plusieurs messages simultanément.Setting this property to a value that is larger than 1 enables the dataflow block to process multiple messages concurrently. Si vous définissez cette propriété sur DataflowBlockOptions.Unbounded, vous permettez au planificateur de tâches sous-jacentes de gérer le degré maximal de concurrence.Setting this property to DataflowBlockOptions.Unbounded enables the underlying task scheduler to manage the maximum degree of concurrency.

Important

Quand vous spécifiez un degré maximal de parallélisme supérieur à 1, plusieurs messages sont traités simultanément. Il se peut donc que les messages ne soient pas traités dans l’ordre dans lequel ils sont reçus.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. Toutefois, les messages sont renvoyés du bloc dans le même ordre qu’ils ont été reçus.The order in which the messages are output from the block is, however, the same one in which they are received.

Étant donné que la propriété MaxDegreeOfParallelism représente le degré maximal de parallélisme, le bloc de flux de données peut s'exécuter avec un degré de parallélisme moindre spécifié par vos soins.Because the MaxDegreeOfParallelism property represents the maximum degree of parallelism, the dataflow block might execute with a lesser degree of parallelism than you specify. Le bloc de flux de données peut utiliser un degré de parallélisme moindre pour satisfaire ses exigences fonctionnelles ou en cas de manque de ressources système disponibles.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. Un bloc de flux de données n'utilisera jamais un niveau de parallélisme supérieur à celui que vous spécifiez.A dataflow block never chooses more parallelism than you specify.

La valeur de la propriété MaxDegreeOfParallelism est exclusive à chaque objet de bloc de flux de données.The value of the MaxDegreeOfParallelism property is exclusive to each dataflow block object. Par exemple, si chacun des quatre objets de blocs de flux de données spécifie la valeur 1 comme degré maximal de parallélisme, les quatre objets de bloc de flux de données peuvent être exécutés en parallèle.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.

Vous trouverez un exemple dans lequel est défini le degré maximal de parallélisme permettant à des opérations de longue durée d’être exécutées en parallèle sur la page Guide pratique : spécifier le degré de parallélisme dans un bloc de flux de données.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.

Spécification du nombre de messages par tâcheSpecifying the Number of Messages per Task

Les types de blocs de flux de données prédéfinis utilisent des tâches pour traiter plusieurs éléments d'entrée.The predefined dataflow block types use tasks to process multiple input elements. Cela aide à réduire le nombre d'objets de tâches requis pour traiter les données, ce qui permet aux applications de s'exécuter plus efficacement.This helps minimize the number of task objects that are required to process data, which enables applications to run more efficiently. Toutefois, quand les tâches d'un ensemble de blocs de flux de données traitent des données, il est possible que les tâches des autres blocs de flux de données doivent attendre d'être traitées et placer leurs messages dans la file d'attente.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. Pour un meilleur respect de l'ordre des tâches de flux de données, définissez la propriété MaxMessagesPerTask.To enable better fairness among dataflow tasks, set the MaxMessagesPerTask property. Quand MaxMessagesPerTask a la valeur DataflowBlockOptions.Unbounded, qui est la valeur par défaut, la tâche utilisée par un bloc de flux de données traite tous les messages disponibles.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. Quand MaxMessagesPerTask est défini sur une valeur autre que Unbounded, le bloc de flux de données traite au maximum le nombre défini de messages par objet Task.When MaxMessagesPerTask is set to a value other than Unbounded, the dataflow block processes at most this number of messages per Task object. Même si la configuration de la propriété MaxMessagesPerTask peut améliorer le respect de l'ordre des tâches, elle peut aussi entraîner la création par le système de davantage de tâches que nécessaire, réduisant ainsi les performances.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.

Permettre les annulationsEnabling Cancellation

La bibliothèque parallèle de tâches (TPL) fournit un mécanisme qui permet aux tâches de coordonner l'annulation de manière coopérative.The TPL provides a mechanism that enables tasks to coordinate cancellation in a cooperative manner. Pour permettre aux blocs de flux de données de participer à ce mécanisme d'annulation, définissez la propriété CancellationToken.To enable dataflow blocks to participate in this cancellation mechanism, set the CancellationToken property. Quand l'objet CancellationToken est à l'état annulé, tous les blocs de flux de données qui contrôlent ce jeton terminent l'exécution de l'élément actuel, mais ne démarrent pas le traitement des éléments suivants.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. De plus, ces blocs de flux de données effacent les messages mis en mémoire tampon, libèrent les connexions aux blocs sources et cibles, et passent à l'état annulé.These dataflow blocks also clear any buffered messages, release connections to any source and target blocks, and transition to the canceled state. Lors du passage à l'état annulé, la propriété Status de la propriété Completion est définie sur Canceled, sauf si une exception s'est produite lors du traitement.By transitioning to the canceled state, the Completion property has the Status property set to Canceled, unless an exception occurred during processing. Dans ce cas, Status est défini sur Faulted.In that case, Status is set to Faulted.

Vous trouverez un exemple qui montre comment utiliser l’annulation dans une application Windows Forms sur la page Guide pratique : annuler un bloc de flux de données.For an example that demonstrates how to use cancellation in a Windows Forms application, see How to: Cancel a Dataflow Block. Pour plus d’informations sur les annulations dans la bibliothèque parallèle de tâches, consultez la page Annulation de tâches.For more information about cancellation in the TPL, see Task Cancellation.

Spécification des comportements gourmand et non gourmandSpecifying Greedy Versus Non-Greedy Behavior

Plusieurs types de blocs de flux de données de regroupement peuvent fonctionner en mode gourmand ou en mode non gourmand.Several grouping dataflow block types can operate in either greedy or non-greedy mode. Par défaut, les types de blocs de flux de données prédéfinis fonctionnent en mode gourmand.By default, the predefined dataflow block types operate in greedy mode.

Pour les types de blocs de regroupement tels que JoinBlock<T1,T2>, le mode gourmand signifie que le bloc accepte immédiatement les données, même si les données correspondantes avec lesquelles effectuer le regroupement ne sont pas encore disponibles.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. Le mode non gourmand signifie que le bloc diffère tous les messages entrants jusqu'à ce que chacune de ses cibles ait reçu un message, permettant ainsi le regroupement.Non-greedy mode means that the block postpones all incoming messages until one is available on each of its targets to complete the join. Si l'un des messages différés n'est plus disponible, le bloc de regroupement libère tous les messages différés et redémarre le processus.If any of the postponed messages are no longer available, the join block releases all postponed messages and restarts the process. Pour la classe BatchBlock<T>, les comportements gourmand et non gourmand sont similaires, à ceci près qu'en mode non gourmand, un objet BatchBlock<T> diffère tous les messages entrants jusqu'à ce que suffisamment de messages soient disponibles dans plusieurs sources distinctes pour former un lot.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.

Pour spécifier le mode non gourmand pour un bloc de flux de données, définissez Greedy sur False.To specify non-greedy mode for a dataflow block, set Greedy to False. Vous trouverez un exemple qui montre comment utiliser le mode non gourmand pour permettre à plusieurs blocs de regroupement de partager une source de données plus efficacement sur la page Guide pratique : utiliser JoinBlock pour lire des données issues de plusieurs sources.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.

Blocs de flux de données personnalisésCustom Dataflow Blocks

Même si la bibliothèque de flux de données TPL fournit de nombreux types de blocs prédéfinis, vous pouvez créer d'autres types de blocs ayant un comportement personnalisé.Although the TPL Dataflow Library provides many predefined block types, you can create additional block types that perform custom behavior. Implémentez directement les interfaces ISourceBlock<TOutput> ou ITargetBlock<TInput>, ou utilisez la méthode Encapsulate pour créer un bloc complexe qui encapsule le comportement des types de blocs existants.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. Vous trouverez des exemples qui montrent comment implémenter la fonctionnalité de bloc de flux de données personnalisé sur la page Procédure pas à pas : créer un type de bloc de flux de données personnalisé.For examples that show how to implement custom dataflow block functionality, see Walkthrough: Creating a Custom Dataflow Block Type.

TitreTitle DescriptionDescription
Guide pratique : écrire des messages dans un bloc de flux de données et les lireHow to: Write Messages to and Read Messages from a Dataflow Block Montre comment écrire des messages dans un objet BufferBlock<T> et les lire.Demonstrates how to write messages to and read messages from a BufferBlock<T> object.
Guide pratique : implémenter un modèle de flux de données producteur-consommateurHow to: Implement a Producer-Consumer Dataflow Pattern Explique comment utiliser le modèle de flux de données pour implémenter un modèle producteur-consommateur, où le producteur envoie des messages à un bloc de flux de données et le consommateur lit les messages de ce bloc.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.
Guide pratique : exécuter des actions lorsqu’un bloc de flux de données reçoit des donnéesHow to: Perform Action When a Dataflow Block Receives Data Explique comment fournir des délégués aux types de blocs de flux de données d'exécution ActionBlock<TInput>, TransformBlock<TInput,TOutput> et TransformManyBlock<TInput,TOutput>.Describes how to provide delegates to the execution dataflow block types, ActionBlock<TInput>, TransformBlock<TInput,TOutput>, and TransformManyBlock<TInput,TOutput>.
Procédure pas à pas : créer un pipeline de flux de donnéesWalkthrough: Creating a Dataflow Pipeline Explique comment créer un pipeline de flux de données qui télécharge du texte à partir du web et effectue des opérations sur ce texte.Describes how to create a dataflow pipeline that downloads text from the web and performs operations on that text.
Guide pratique : dissocier des blocs de flux de donnéesHow to: Unlink Dataflow Blocks Montre comment utiliser la méthode LinkTo pour dissocier un bloc cible de sa source après que celle-ci lui a envoyé un message.Demonstrates how to use the LinkTo method to unlink a target block from its source after the source offers a message to the target.
Procédure pas à pas : utiliser les flux de données dans une application Windows FormsWalkthrough: Using Dataflow in a Windows Forms Application Montre comment créer un réseau de blocs de flux de données qui effectuent un traitement des images dans une application Windows Forms.Demonstrates how to create a network of dataflow blocks that perform image processing in a Windows Forms application.
Guide pratique : annuler un bloc de flux de donnéesHow to: Cancel a Dataflow Block Montre comment utiliser l'annulation dans une application Windows Forms.Demonstrates how to use cancellation in a Windows Forms application.
Guide pratique : utiliser JoinBlock pour lire des données issues de plusieurs sourcesHow to: Use JoinBlock to Read Data From Multiple Sources Explique comment utiliser la classe JoinBlock<T1,T2> pour effectuer une opération quand des données sont disponibles dans plusieurs sources, et comment utiliser le mode non gourmand pour permettre à plusieurs blocs de regroupement de partager une source de données plus efficacement.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.
Guide pratique : spécifier le degré de parallélisme dans un bloc de flux de donnéesHow to: Specify the Degree of Parallelism in a Dataflow Block Explique comment définir la propriété MaxDegreeOfParallelism pour permettre à un bloc de flux de données d'exécution de traiter plusieurs messages à la fois.Describes how to set the MaxDegreeOfParallelism property to enable an execution dataflow block to process more than one message at a time.
Guide pratique : spécifier un planificateur de tâches dans un bloc de flux de donnéesHow to: Specify a Task Scheduler in a Dataflow Block Montre comment associer un planificateur de tâches spécifique quand vous utilisez un flux de données dans votre application.Demonstrates how to associate a specific task scheduler when you use dataflow in your application.
Procédure pas à pas : utiliser BatchBlock et BatchedJoinBlock pour améliorer l’efficacitéWalkthrough: Using BatchBlock and BatchedJoinBlock to Improve Efficiency Explique comment utiliser la classe BatchBlock<T> pour améliorer l'efficacité des opérations d'insertion de bases de données, et comment utiliser la classe BatchedJoinBlock<T1,T2> pour capturer les résultats et les exceptions qui se produisent quand le programme lit les données d'une base de données.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.
Procédure pas à pas : créer un type de bloc de flux de données personnaliséWalkthrough: Creating a Custom Dataflow Block Type Montre deux façons de créer un type de bloc de flux de données qui implémente un comportement personnalisé.Demonstrates two ways to create a dataflow block type that implements custom behavior.
La bibliothèque parallèle de tâchesTask Parallel Library (TPL) Présente la bibliothèque parallèle de tâches (TPL), qui simplifie la programmation parallèle et simultanée dans les applications .NET Framework.Introduces the TPL, a library that simplifies parallel and concurrent programming in .NET Framework applications.