Flux de données (bibliothèque parallèle de tâches)

.NET Framework (current version)
 

Date de publication : novembre 2016

La bibliothèque parallèle de tâches (TPL) fournit des composants de flux de données pour améliorer la robustesse des applications d’accès concurrentiel. Ces composants de flux de données sont collectivement appelés le bibliothèque de flux de données TPL. 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". 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. 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. Prenons par exemple une application qui traite les données d'image d'une webcam. En utilisant le modèle de flux de données, l'application peut traiter les trames d'images à mesure qu'elles deviennent disponibles. Si l’application améliore les trames d’images, par exemple, en effectuant la lumière de correction ou des yeux rouges, vous pouvez créer un pipeline des composants de flux de données. 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.

Ce document fournit une vue d'ensemble de la bibliothèque de flux de données TPL. 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.

System_CAPS_ICON_tip.jpg Astuce

La bibliothèque de flux de données TPL (System.Threading.Tasks.Dataflow espace de noms) n’est pas distribuée avec le .NET Framework 4.5. Pour installer le System.Threading.Tasks.Dataflow espace de noms, ouvrez votre projet dans Visual Studio 2012, choisissez Manage NuGet Packages à partir du menu projet, puis recherchez en ligne pour le Microsoft.Tpl.Dataflow package.

Ce document contient les sections suivantes :

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. 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. 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. 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. À 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. 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. 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. 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. Pour obtenir un exemple qui utilise le modèle de programmation de flux de données pour implémenter le traitement d’image dans une application Windows Forms, consultez procédure pas à pas : utilisation des flux de données dans une Application Windows Forms.

Sources et cibles

La bibliothèque de flux de données TPL comprend blocs de flux de données, qui sont des données de structures cette mémoire tampon et traiter les données. La bibliothèque parallèle de tâches définit trois types de blocs de flux de données : blocs sources, blocs cibles, et blocs propagateurs. Un bloc source agit comme une source de données et peut donc être lu. Un bloc cible joue le rôle de récepteur de données, il est donc possible d'y écrire. 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. La bibliothèque parallèle de tâches définit les System.Threading.Tasks.Dataflow.ISourceBlock<> </> > interface pour représenter les sources, System.Threading.Tasks.Dataflow.ITargetBlock<> </> > pour représenter les cibles, et System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput, TOutput> pour représenter les propagateurs.</TInput, TOutput> IPropagatorBlock<TInput, TOutput> hérite à la fois ISourceBlock<>>, et ITargetBlock<>>.</TInput, TOutput>

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 la ISourceBlock<>>, ITargetBlock<>>, et IPropagatorBlock<TInput, TOutput> interfaces.</TInput, TOutput> Ces types de blocs de flux de données sont décrites dans ce document dans la section prédéfinis de Types de blocs de flux de données.

Connexion des blocs

Vous pouvez connecter des blocs de flux de données pour former pipelines, qui sont des séquences linéaires de blocs de flux de données, ou réseaux, qui sont des graphiques des blocs de flux de données. Un pipeline est une forme de réseau. 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. Le ISourceBlock<>>. Liaisonavec méthode lie un bloc de flux de données source à un bloc cible. Une source peut être liée à zéro, une ou plusieurs cibles. Une cible peut être liée à zéro, une ou plusieurs sources. Vous pouvez ajouter des blocs de flux de données à un pipeline ou en supprimer de manière simultanée. 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.

Pour obtenir un exemple qui connecte des blocs de flux de données pour former un pipeline de base, consultez procédure pas à pas : création d’un Pipeline de flux de données. Pour obtenir un exemple qui connecte des blocs de flux de données pour former un réseau plus complexe, consultez procédure pas à pas : utilisation des flux de données dans une Application Windows Forms. Pour obtenir un exemple qui supprime une cible d’une source après que la cible un message, consultez Comment : dissocier des blocs de flux de données.

Filtrage

Lorsque vous appelez le ISourceBlock<>>. Liaisonavec méthode pour lier une source vers une cible, vous pouvez fournir un délégué qui détermine si le bloc cible accepte ou rejette un message en fonction de la valeur de ce message. Ce mécanisme de filtrage permet de garantir qu'un bloc de flux de données recevra uniquement certaines valeurs. 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. 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. La plupart des types de blocs sources arrêtent d'envoyer un message une fois celui-ci accepté par une cible. Une exception à cette règle est la BroadcastBlock<> </> > (classe), qui offre de chaque message à toutes les cibles, même si certaines cibles rejettent le message. Pour obtenir un exemple qui utilise le filtrage pour traiter uniquement certains messages, consultez procédure pas à pas : utilisation des flux de données dans une Application Windows Forms.

System_CAPS_ICON_important.jpg 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. 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. Sinon, votre application peut se bloquer.

Transmission de messages

Le modèle de programmation de flux de données est lié au concept de passage de messages, où les composants indépendants d’un programme communiquent entre eux en envoyant des messages. Une façon de propager des messages entre les composants d’application consiste à appeler le Post<> </> > et DataflowBlock.SendAsync<> </> > des méthodes pour envoyer des messages POST de blocs de flux de données cible (valider<> </> > agit de manière synchrone ; SendAsync<> </> > asynchrone) et le réception<>>, ReceiveAsync<>>, et TryReceive<> </> > méthodes pour recevoir des messages à partir de blocs de code source. 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). Vous pouvez également utiliser le choisir pour lire à partir de la première méthode de sources fournies qui contient des données et effectuer des actions sur ces données.

Blocs sources envoient des données aux blocs cibles en appelant le ITargetBlock<>>. OfferMessage (méthode). Le bloc cible peut répondre à un message envoyé de trois manières : il peut accepter le message, le refuser ou le différer. Lorsque la cible accepte le message, le OfferMessage méthode renvoie accepté. Lorsque la cible refuse le message, le OfferMessage méthode renvoie refusé. Quand la cible qu’il ne reçoive plus tous les messages à partir de la source, OfferMessage retourne 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.

Lorsqu’un bloc cible diffère le message pour une utilisation ultérieure, le OfferMessage méthode renvoie mis en pause. Un bloc cible qui diffère un message peut appeler ultérieurement la ISourceBlock<>>. ReserveMessage méthode pour tenter de réserver le message envoyé. À 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. Lorsque le bloc cible nécessite ultérieurement le message ou n’a plus besoin du message, il appelle le ISourceBlock<>>. ConsumeMessage ou ReleaseReservation (méthode), respectivement. 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. Le mode non gourmand est expliqué plus loin dans ce document. Plutôt que de réserver un message différé, un bloc cible peut également utiliser le ISourceBlock<>>. ConsumeMessage méthode tente d’utiliser directement le message différé.

Achèvement des blocs de flux de données

Les blocs de flux de données prennent également en charge le concept de fin. Un bloc de flux de données qui est achevé n'effectue plus aucune tâche. Chaque bloc de flux de données est associé à un System.Threading.Tasks.Task objet, appelé un tâche d’achèvement, qui représente l’état d’achèvement du bloc. Étant donné que vous pouvez attendre un tâche pour terminer, à l’aide de tâches d’exécution, vous pouvez attendre d’un ou plusieurs nœuds terminaux d’un flux de données réseau à la fin de l’objet. Le IDataflowBlock interface définit les Complete (méthode), qui informe le bloc de flux de données d’une requête pour qu’elle se termine, et le fin propriété qui retourne la tâche d’achèvement pour le bloc de flux de données. Les deux ISourceBlock<> </> > et ITargetBlock<> </> > héritent la 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é. La première consiste à appeler le Task.Wait méthode sur la tâche d’achèvement dans un try - catch bloc (Try - Catch en Visual Basic). L’exemple suivant crée un ActionBlock<> </> > objet lève une exception ArgumentOutOfRangeException si sa valeur d’entrée est inférieur à zéro. AggregateException est levée quand cet exemple appelle attente sur la tâche d’achèvement. Le ArgumentOutOfRangeException est accessible via la InnerExceptions propriétés de la AggregateException objet.

         // 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.
         */

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. Nous vous recommandons de gérer les exceptions dans le corps des blocs. 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.

Lorsqu’un bloc de flux de données est annulé de manière explicite, le AggregateException objet contient OperationCanceledException dans les InnerExceptions propriété. Pour plus d'informations sur l'annulation de flux de données, consultez la section "Permettre les annulations" plus loin dans ce document.

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. Le délégué que vous fournissez à la Task.ContinueWith méthode prend un tâche objet qui représente la tâche précédente. Dans le cas de la fin propriété, le délégué de la continuation prend la tâche d’achèvement. L’exemple suivant ressemble au précédent, sauf qu’elle utilise également la ContinueWith pour créer une tâche d’achèvement qui imprime l’état de l’opération de flux de données globale.

         // 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.
         */

Vous pouvez également utiliser des propriétés telles que IsCanceled dans le corps de la tâche de continuation pour déterminer des informations supplémentaires sur l’état d’achèvement d’un bloc de flux de données. Pour plus d’informations sur les tâches de continuation et leur interaction pour l’annulation et la gestion des erreurs, consultez la page chaînage des tâches à l’aide de tâches de Continuation, l’annulation de tâche, la gestion des exceptions, et NIB : Comment : gérer les Exceptions levées par des tâches.

[go to top]

La bibliothèque de flux de données TPL fournit plusieurs types de blocs de flux de données prédéfinis. Ces types sont divisés en trois catégories : blocs de mise en mémoire tampon, blocs d’exécution, et blocs de regroupement. Les sections suivantes décrivent les types de blocs qui composent ces catégories.

Blocs de mise en mémoire tampon

Les blocs de mise en mémoire tampon contiennent des données destinées aux consommateurs de données. 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<>>, System.Threading.Tasks.Dataflow.BroadcastBlock<>>, et System.Threading.Tasks.Dataflow.WriteOnceBlock<>>.

BufferBlock(T)

Le BufferBlock<> </> > classe représente une structure de messagerie asynchrone à usage général. 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. Quand une cible reçoit un message d’un BufferBlock<> </> > de l’objet, ce message est supprimé de la file d’attente. Par conséquent, bien qu’un BufferBlock<> </> > objet peut avoir plusieurs cibles, qu’une seule cible reçoit chaque message. Le BufferBlock<> </> > classe est utile lorsque vous voulez passer plusieurs messages à un autre composant, et que le composant doit recevoir chaque message.

L’exemple de base suivant publie plusieurs Int32 valeurs à un BufferBlock<> </> > de l’objet, puis le lit ces valeurs à partir de cet objet.

         // 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
          */

Pour un exemple complet qui montre comment écrire et lire des messages d’un BufferBlock<> </> > , consultez Comment : écrire et lire des Messages à partir d’un Dataflow Block.

BroadcastBlock(T)

Le BroadcastBlock<> </> > classe est utile lorsque vous devez transmettre plusieurs messages à un autre composant, mais que ce composant nécessite uniquement la valeur la plus récente. Cette classe est également utile quand vous voulez diffuser un message vers plusieurs composants.

Les publications de l’exemple de base suivant un Double valeur un BroadcastBlock<> </> > objet puis lue à partir de cet objet plusieurs fois. Étant donné que les valeurs ne sont pas supprimés de BroadcastBlock<> </> > objets après leur lecture, la même valeur est disponible à chaque fois.

         // 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
          */

Pour un exemple complet qui montre comment utiliser BroadcastBlock<> </> > pour diffuser un message à plusieurs blocs cibles, consultez Comment : spécifier un planificateur de tâches dans un Dataflow Block.

WriteOnceBlock(T)

Le WriteOnceBlock<> </> > ressemble à la BroadcastBlock<> </> > de classe, à ceci près qu’un WriteOnceBlock<> </> > objet peut être écrites dans une seule fois. Vous pouvez considérer WriteOnceBlock<> </> > est similaire à celle de C# readonly (ReadOnly dans Visual Basic) (mot clé), à ceci près qu’un WriteOnceBlock<> </> > objet est immuable après avoir reçu une valeur au moment de construction. Comme le BroadcastBlock<> </> > (classe), lorsqu’une cible reçoit un message d’un WriteOnceBlock<> </> > de l’objet, ce message n’est pas supprimé de cet objet. Par conséquent, plusieurs cibles reçoivent une copie du message. Le WriteOnceBlock<> </> > classe est utile lorsque vous voulez propager uniquement la première de plusieurs messages.

L’exemple de base suivant publie plusieurs chaîne valeurs à un WriteOnceBlock<> </> > objet, puis lit la valeur de retour de cet objet. Car un WriteOnceBlock<> </> > objet peut être écrites dans une seule fois, une fois qu’un WriteOnceBlock<> </> > objet reçoit un message, il rejette les messages suivants.

         // 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
          */

Pour un exemple complet qui montre comment utiliser WriteOnceBlock<> </> > pour recevoir la valeur de la première opération se termine, consultez Comment : dissocier des blocs de flux de données.

Blocs d'exécution

Les blocs d'exécution appellent un délégué fourni par l'utilisateur pour chaque donnée reçue. La bibliothèque de flux de données TPL fournit trois types de blocs d’exécution : ActionBlock<>>, System.Threading.Tasks.Dataflow.TransformBlock<TInput, TOutput>, et System.Threading.Tasks.Dataflow.TransformManyBlock<TInput, TOutput>.</TInput, TOutput> </TInput, TOutput>

ActionBlock(T)

Le ActionBlock<> </> > classe est un bloc cible qui appelle un délégué lorsqu’il reçoit des données. Considérez un ActionBlock<> </> > objet sous la forme d’un délégué qui s’exécute de façon asynchrone lorsque les données deviennent disponibles. Le délégué que vous fournissez à un ActionBlock<> </> > objet peut être de type Action ou System.Func<TInput, Task>. Lorsque vous utilisez un ActionBlock<> </> > avec l’objet Action, le traitement de chaque élément d’entrée est considéré comme terminé quand le délégué est retourné. Lorsque vous utilisez un ActionBlock<> </> > avec l’objet System.Func<TInput, Task>, traitement de chaque élément d’entrée est considéré comme terminé que quand retourné tâches objet est terminé. À l’aide de ces deux mécanismes, vous pouvez utiliser ActionBlock<> </> > pour le traitement synchrone et asynchrone de chaque élément d’entrée.

L’exemple de base suivant publie plusieurs Int32 valeurs à un ActionBlock<> </> > objet. Le ActionBlock<> </> > objet imprime ces valeurs dans la 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.

         // 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
          */

Pour obtenir des exemples complets qui montrent comment utiliser des délégués avec les ActionBlock<> </> > de classe, consultez la page Comment : effectuer Action lorsqu’un flux de données bloc reçoit des données.

TransformBlock(TInput, TOutput)

Le TransformBlock<TInput, TOutput> ressemble à la ActionBlock<> </> > classe, sauf qu’il fait à la fois en tant que source et cible.</TInput, TOutput> Le délégué que vous passez à un TransformBlock<TInput, TOutput> objet renvoie une valeur de type TOutput.</TInput, TOutput> Le délégué que vous fournissez à un TransformBlock<TInput, TOutput> objet peut être de type System.Func<TInput, TOutput> ou System.Func<TInput, Task>.</TInput, TOutput> Lorsque vous utilisez un TransformBlock<TInput, TOutput> avec l’objet System.Func<TInput, TOutput>, le traitement de chaque élément d’entrée est considéré comme terminé lorsque le délégué retourne.</TInput, TOutput> Lorsque vous utilisez un TransformBlock<TInput, TOutput> objet utilisé avec System.Func<TInput, Task<TOutput>>, traitement de chaque élément d’entrée est considéré comme terminé que quand retourné tâche objet terminé.</TInput, TOutput> Comme avec ActionBlock<>>, à l’aide de ces deux mécanismes, vous pouvez utiliser TransformBlock<TInput, TOutput> pour le traitement synchrone et asynchrone de chaque élément d’entrée.</TInput, TOutput>

L’exemple de base suivant crée un TransformBlock<TInput, TOutput> objet qui calcule la racine carrée de son entrée.</TInput, TOutput> Le TransformBlock<TInput, TOutput> prend de l’objet Int32 valeurs comme entrée et produit Double valeurs en tant que sortie.</TInput, TOutput>

         // 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
          */

Pour obtenir des exemples complets qui utilise TransformBlock<TInput, TOutput> dans un réseau de blocs de flux de données qui effectue le traitement de l’image dans une application Windows Forms, consultez procédure pas à pas : utilisation des flux de données dans une Application Windows Forms.</TInput, TOutput>

TransformManyBlock(TInput, TOutput)

Le TransformManyBlock<TInput, TOutput> ressemble à la TransformBlock<TInput, TOutput> de classe, à ceci près que TransformManyBlock<TInput, TOutput> produit zéro ou plusieurs valeurs de sortie pour chaque valeur d’entrée, et non uniquement une valeur de sortie pour chaque valeur d’entrée.</TInput, TOutput> </TInput, TOutput> </TInput, TOutput> Le délégué que vous fournissez à un TransformManyBlock<TInput, TOutput> objet peut être de type System.Func<TInput, IEnumerable<TOutput>> ou type System.Func<TInput, Task<IEnumerable<TOutput>>>.</TInput, TOutput> Lorsque vous utilisez un TransformManyBlock<TInput, TOutput> avec l’objet System.Func<TInput, IEnumerable<TOutput>>, le traitement de chaque élément d’entrée est considéré comme terminé lorsque le délégué retourne.</TInput, TOutput> Lorsque vous utilisez un TransformManyBlock<TInput, TOutput> avec l’objet System.Func<TInput, Task<IEnumerable<TOutput>>>, traitement de chaque élément d’entrée est considéré comme terminé uniquement lorsque retourné System.Threading.Tasks.Task<IEnumerable<TOutput>> objet est terminé.</TInput, TOutput>

L’exemple de base suivant crée un TransformManyBlock<TInput, TOutput> objet qui fractionne les chaînes en leurs séquences de caractères individuels.</TInput, TOutput> Le TransformManyBlock<TInput, TOutput> prend de l’objet chaîne valeurs comme entrée et produit Char valeurs en tant que sortie.</TInput, TOutput>

         // 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
          */

Pour obtenir des exemples complets qui utilisent TransformManyBlock<TInput, TOutput> pour produire des sorties multiples indépendantes pour chaque entrée dans un pipeline de flux de données, consultez procédure pas à pas : création d’un Pipeline de flux de données.</TInput, TOutput>

Degré de parallélisme

Chaque ActionBlock<>>, TransformBlock<TInput, TOutput>, et TransformManyBlock<TInput, TOutput> tampons de l’objet des messages entrants jusqu'à ce que le bloc soit prêt à les traiter.</TInput, TOutput> </TInput, TOutput> Par défaut, ces classes de traitent les messages un par un, dans l'ordre dans lequel ils sont reçus. Vous pouvez également spécifier le degré de parallélisme pour activer ActionBlock<>>, TransformBlock<TInput, TOutput> et TransformManyBlock<TInput, TOutput> objets à traiter plusieurs messages simultanément.</TInput, TOutput> </TInput, TOutput> 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. Pour obtenir un exemple qui définit le degré de parallélisme pour permettre à un bloc de flux de données d’exécution traiter plusieurs messages à la fois, consultez Comment : spécifier le degré de parallélisme dans un Dataflow Block.

Récapitulation des types délégués

Le tableau suivant récapitule les types délégués que vous pouvez fournir aux ActionBlock<>>, TransformBlock<TInput, TOutput>, et TransformManyBlock<TInput, TOutput> objets.</TInput, TOutput> </TInput, TOutput> Le tableau indique également si le type délégué fonctionne de façon synchrone ou asynchrone.

TypeType délégué synchroneType délégué asynchrone
ActionBlock<>>System.ActionSystem.Func<TInput, Task>
TransformBlock<TInput, TOutput></TInput, TOutput>System.Func<TInput, TOutput>2`System.Func<TInput, Task<TOutput>>
TransformManyBlock<TInput, TOutput></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. Pour obtenir un exemple qui montre comment utiliser une expression lambda avec un bloc d’exécution, consultez Comment : effectuer Action lorsqu’un flux de données bloc reçoit des données.

Blocs de regroupement

Les blocs de regroupement combinent les données d'une ou plusieurs sources, sous diverses contraintes. La bibliothèque de flux de données TPL fournit trois types de blocs de jointure : BatchBlock<>>, JoinBlock<T1, T2>, et BatchedJoinBlock<T1, T2>.</T1, T2> </T1, T2>

BatchBlock(T)

Le BatchBlock<> </> > classe combine des jeux de données d’entrée, qui sont appelées des lots, dans les tableaux de données de sortie. Vous spécifiez la taille de chaque lot lorsque vous créez un BatchBlock<> </> > objet. Lors de la BatchBlock<> </> > objet reçoit le nombre spécifié d’éléments d’entrée, il propage de manière asynchrone un tableau qui contient ces éléments. Si un BatchBlock<> </> > objet est défini sur l’état terminé mais ne contient-elle pas suffisamment d’éléments pour former un lot, il propage un tableau final contenant les éléments d’entrée restants.

Le BatchBlock<> </> > classe s’exécute en mode gourmand ou non gourmand mode. En mode gourmand, qui est la valeur par défaut, un BatchBlock<> </> > objet accepte tous les messages qu’il est proposé et propage un tableau après avoir reçu le nombre spécifié d’éléments. En mode non gourmand, un BatchBlock<> </> > objet diffère tous les messages entrants jusqu'à ce que suffisamment sources ont offert des messages vers le bloc pour former un lot. Le mode gourmand est généralement plus performant que le mode non gourmand, car il nécessite une charge de traitement moindre. Toutefois, vous pouvez utiliser le mode non gourmand quand vous devez coordonner la consommation de plusieurs sources de façon atomique. Spécifiez le mode non gourmand en définissant gourmands à False dans les dataflowBlockOptions paramètre dans le BatchBlock<> </> > constructeur.

L’exemple de base suivant publie plusieurs Int32 valeurs à un BatchBlock<> </> > objet qui contient les dix éléments dans un lot. Pour garantir que toutes les valeurs sont propagées de la BatchBlock<>>, cet exemple appelle la Complete (méthode). Le Complete méthode définit les BatchBlock<> </> > objet à l’état terminé et par conséquent, le BatchBlock<> </> > objet propage les éléments restants dans un dernier lot.

         // 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.
          */

Pour un exemple complet qui utilise BatchBlock<> </> > pour améliorer l’efficacité des opérations d’insertion de base de données, consultez procédure pas à pas : utilisation de BatchBlock et de BatchedJoinBlock pour améliorer l’efficacité.

JoinBlock(T1, T2,...)

Le JoinBlock<T1, T2> et JoinBlock<T1, T2, T3> classes collectent des éléments d’entrée et propagent les System.Tuple<T1, T2> ou System.Tuple<T1, T2, T3> objets qui contiennent ces éléments.</T1, T2, T3> </T1, T2> </T1, T2, T3> </T1, T2> Le JoinBlock<T1, T2> et JoinBlock<T1, T2, T3> classes n’héritent pas de ITargetBlock<>>.</T1, T2, T3> </T1, T2> Au lieu de cela, elles fournissent les propriétés Target1, Target2, et Target3, qui implémentent ITargetBlock<>>.

Comme BatchBlock<>>, JoinBlock<T1, T2> et JoinBlock<T1, T2, T3> fonctionner en mode gourmand ou non gourmand.</T1, T2, T3> </T1, T2> En mode gourmand, qui est la valeur par défaut, un JoinBlock<T1, T2> ou JoinBlock<T1, T2, T3> objet accepte tous les messages qu’il est proposé et propage un tuple après chacune de ses cibles reçoit au moins un message.</T1, T2, T3> </T1, T2> En mode non gourmand, un JoinBlock<T1, T2> ou JoinBlock<T1, T2, T3> objet diffère tous les messages entrants jusqu'à ce que toutes les cibles ont été proposés les données requises pour créer un tuple.</T1, T2, T3> </T1, T2> À 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. Ce report permet à une autre entité de consommer les données pendant ce temps, pour que l'ensemble du système puisse progresser.

L’exemple de base suivant montre un cas dans lequel un JoinBlock<T1, T2, T3> objet nécessite plusieurs données pour calculer une valeur.</T1, T2, T3> Cet exemple crée un JoinBlock<T1, T2, T3> objet nécessite deux Int32 valeurs et un Char valeur pour effectuer une opération arithmétique.</T1, T2, T3>

         // 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
          */

Pour un exemple complet qui utilise JoinBlock<T1, T2> en mode non gourmand en coopération partager une ressource, consultez Comment : utiliser JoinBlock pour lire des données à partir de plusieurs Sources.</T1, T2>

BatchedJoinBlock(T1, T2, ...)

Le BatchedJoinBlock<T1, T2> et BatchedJoinBlock<T1, T2, T3> classes collectent des lots d’éléments d’entrée et propagent les System.Tuple(IList(T1), IList(T2)) ou System.Tuple(IList(T1), IList(T2), IList(T3)) les objets qui contiennent ces éléments.</T1, T2, T3> </T1, T2> Pensez à BatchedJoinBlock<T1, T2> comme une combinaison de BatchBlock<> </> > et JoinBlock<T1, T2>.</T1, T2> </T1, T2> Spécifiez la taille de chaque lot lorsque vous créez un BatchedJoinBlock<T1, T2> objet.</T1, T2> BatchedJoinBlock<T1, T2> fournit également les propriétés Target1 et Target2, qui implémentent ITargetBlock<>>.</T1, T2> Lorsque le nombre spécifié d’éléments d’entrée sont reçus à partir de sur toutes les cibles, les BatchedJoinBlock<T1, T2> objet propage de manière asynchrone une System.Tuple(IList(T1), IList(T2)) objet qui contient ces éléments.</T1, T2>

L’exemple de base suivant crée un BatchedJoinBlock<T1, T2> objet qui conserve des résultats, Int32 les valeurs et les erreurs qui sont Exception objets.</T1, T2> Cet exemple effectue plusieurs opérations et écrit les résultats de la Target1 propriété et les erreurs dans le Target2 propriété, de la BatchedJoinBlock<T1, T2> objet.</T1, T2> Étant donné que le nombre d’opérations réussies et échouées est inconnu à l’avance, le IList<> </> > objets permettent à chaque cible de recevoir des valeurs zéro ou plus.

         // 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.
          */

Pour un exemple complet qui utilise BatchedJoinBlock<T1, T2> pour capturer les résultats et les exceptions qui se produisent lorsque le programme lit à partir d’une base de données, consultez procédure pas à pas : utilisation de BatchBlock et de BatchedJoinBlock pour améliorer l’efficacité.</T1, T2>

[go to top]

Vous pouvez activer des options supplémentaires en fournissant un System.Threading.Tasks.Dataflow.DataflowBlockOptions objet au constructeur de types de blocs de flux de données. 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. Le DataflowBlockOptions également a types dérivés qui spécifient le comportement spécifique à certains types de blocs de flux de données. Le tableau suivant récapitule les types d'options qui sont associés à chaque type de bloc de flux de données.

Type de bloc de flux de donnéesDataflowBlockOptions type
BufferBlock<>>DataflowBlockOptions
BroadcastBlock<>>DataflowBlockOptions
WriteOnceBlock<>>DataflowBlockOptions
ActionBlock<>>ExecutionDataflowBlockOptions
TransformBlock<TInput, TOutput></TInput, TOutput>ExecutionDataflowBlockOptions
TransformManyBlock<TInput, TOutput></TInput, TOutput>ExecutionDataflowBlockOptions
BatchBlock<>>GroupingDataflowBlockOptions
JoinBlock<T1, T2></T1, T2>GroupingDataflowBlockOptions
BatchedJoinBlock<T1, T2></T1, T2>GroupingDataflowBlockOptions

Les sections suivantes fournissent des informations supplémentaires sur les types de flux de données importants d’options de bloc qui sont disponibles via la System.Threading.Tasks.Dataflow.DataflowBlockOptions, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions, et System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions classes.

Spécification du planificateur de tâches

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. Planificateur de tâches est une classe abstraite qui représente un planificateur de tâches en file d’attente de tâches sur des threads. Le Planificateur de tâches par défaut, par défaut, utilise le ThreadPool classe à la file d’attente et les exécuter. Vous pouvez remplacer le Planificateur de tâches par défaut en définissant le TaskScheduler propriété lorsque vous construisez un objet de bloc de flux de données.

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. Par exemple, si plusieurs blocs de flux de données sont toutes configurées pour cibler le planificateur exclusif du même ConcurrentExclusiveSchedulerPair de l’objet, tout le travail qu’exécutées dans ces blocs sont sérialisées. De même, si ces blocs sont configurés pour cibler le planificateur simultané du même ConcurrentExclusiveSchedulerPair objet et que le planificateur est configuré pour avoir un niveau d’accès concurrentiel maximal, tout le travail à partir de ces blocs est limité au nombre d’opérations simultanées. Pour obtenir un exemple qui utilise le ConcurrentExclusiveSchedulerPair classe pour permettre les opérations de lecture se produisent en parallèle, mais écrire des opérations de se produire exclusivement de toutes les autres opérations, consultez Comment : spécifier un planificateur de tâches dans un Dataflow Block. Pour plus d’informations sur les planificateurs de tâches dans la bibliothèque parallèle de tâches, consultez la TaskScheduler rubrique de la classe.

Spécification du degré de parallélisme

Par défaut, les types de blocs de trois exécution par la bibliothèque de flux de données TPL, ActionBlock<>>, TransformBlock<TInput, TOutput>, et TransformManyBlock<TInput, TOutput>, traiter un message à la fois.</TInput, TOutput> </TInput, TOutput> Ces types de blocs de flux de données traitent également les messages dans l'ordre dans lequel ils sont reçus. Pour activer ces blocs de flux de données traiter simultanément les messages, définissez les ExecutionDataflowBlockOptions.MaxDegreeOfParallelism propriété lorsque vous construisez l’objet de bloc de flux de données.

La valeur par défaut MaxDegreeOfParallelism est 1, ce qui garantit que le bloc de flux de données traite un message à la fois. 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. Si cette propriété DataflowBlockOptions.Unbounded permet au planificateur de tâches sous-jacente gérer le degré maximal de concurrence.

System_CAPS_ICON_important.jpg 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. Toutefois, l'ordre dans lequel les messages sont générés à partir du bloc reste le même.

Étant donné que la MaxDegreeOfParallelism propriété 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 que vous spécifiez. 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. Un bloc de flux de données n'utilisera jamais un niveau de parallélisme supérieur à celui que vous spécifiez.

La valeur de la MaxDegreeOfParallelism propriété est exclusive à chaque objet de bloc de flux de données. 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.

Pour obtenir un exemple qui définit le degré maximal de parallélisme pour activer les opérations de longue durée se produisent en parallèle, consultez Comment : spécifier le degré de parallélisme dans un Dataflow Block.

Spécification du nombre de messages par tâche

Les types de blocs de flux de données prédéfinis utilisent des tâches pour traiter plusieurs éléments d'entrée. 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. 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. Pour permettre une meilleure justesse parmi les tâches de flux de données, définissez la MaxMessagesPerTask propriété. Lors de la MaxMessagesPerTask a 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 sont disponibles. Lors de la MaxMessagesPerTask est définie sur une valeur autre que Unbounded, le bloc de flux de données traite au maximum le nombre de messages par tâche objet. Bien que la configuration du MaxMessagesPerTask propriété peut augmenter équité entre des tâches, il peut entraîner le système créer des tâches plus que nécessaire, ce qui peut réduire les performances.

Permettre les annulations

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. Pour activer des blocs de flux de données de participer à ce mécanisme d’annulation, définissez la CancellationToken propriété. Lorsque cela CancellationToken objet est défini à 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. 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é. Lors du passage à l’état annulé, la fin propriété a le état propriété annulé, sauf si une exception s’est produite lors du traitement. Dans ce cas, état a Faulted.

Pour obtenir un exemple qui montre comment utiliser l’annulation dans une application Windows Forms, consultez Comment : annuler une Dataflow Block. Pour plus d’informations sur l’annulation dans la bibliothèque parallèle de tâches, consultez la page l’annulation de tâche.

Spécification des comportements gourmand et non gourmand

Plusieurs types de blocs de flux de données de regroupement peuvent fonctionner en mode gourmand ou non gourmand mode. Par défaut, les types de blocs de flux de données prédéfinis fonctionnent en mode gourmand.

À la jointure de bloquer des types 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 laquelle joindre ne sont pas encore disponibles.</T1, T2> 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. 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. Pour le BatchBlock<> </> > classe gourmand et non gourmand est similaire, à ceci près qu’en mode non gourmand, un BatchBlock<> </> > objet diffère tous les messages entrants jusqu'à ce que suffisamment sont disponibles à partir de sources distinctes pour former un lot.

Pour spécifier le mode non gourmand pour un bloc de flux de données, définissez gourmands à False. Pour obtenir un exemple qui montre comment utiliser le mode non gourmand pour permettre à plusieurs blocs de partager une source de données plus efficacement, consultez Comment : utiliser JoinBlock pour lire des données à partir de plusieurs Sources.

[go to top]

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é. Implémentez la ISourceBlock<> </> > ou ITargetBlock<> </> > interagit directement ou utiliser les encapsuler<TInput, TOutput> méthode pour créer un bloc complex qui encapsule le comportement des types de blocs existants.</TInput, TOutput> Pour obtenir des exemples qui montrent comment implémenter la fonctionnalité de bloc de flux de données personnalisé, consultez procédure pas à pas : création d’un Type de bloc de flux de données personnalisé.

[go to top]

TitreDescription
Comment : écrire et lire des Messages à partir d’un bloc de flux de donnéesMontre comment écrire et lire des messages d’un BufferBlock<> </> > objet.
Comment : implémenter un modèle de flux de données producteur-consommateurExplique 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.
Comment : exécuter des actions lorsqu’un bloc de flux de données reçoit des donnéesDécrit comment fournir des délégués pour les types de blocs de flux de données d’exécution, ActionBlock<>>, TransformBlock<TInput, TOutput>, et TransformManyBlock<TInput, TOutput>.</TInput, TOutput> </TInput, TOutput>
Procédure pas à pas : Création d’un Pipeline de flux de donnéesExplique 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.
Comment : dissocier des blocs de flux de donnéesMontre comment utiliser le liaisonavec méthode pour dissocier un bloc cible à partir de sa source une fois la source envoie un message à la cible.
Procédure pas à pas : Utilisation de flux de données dans une Application Windows FormsMontre comment créer un réseau de blocs de flux de données qui effectuent un traitement des images dans une application Windows Forms.
Comment : annuler un bloc de flux de donnéesMontre comment utiliser l'annulation dans une application Windows Forms.
Comment : utiliser JoinBlock pour lire les données provenant de plusieurs SourcesExplique comment utiliser le JoinBlock<T1, T2> classe pour effectuer une opération lorsque les données sont disponibles à partir de plusieurs sources et comment utiliser le mode non gourmand pour permettre à plusieurs blocs de partager une source de données plus efficacement.</T1, T2>
Comment : spécifier le degré de parallélisme dans un bloc de flux de donnéesDécrit comment définir le MaxDegreeOfParallelism propriété pour activer un bloc de flux de données d’exécution traiter plusieurs messages à la fois.
Comment : spécifier un planificateur de tâches dans un bloc de flux de donnéesMontre comment associer un planificateur de tâches spécifique quand vous utilisez un flux de données dans votre application.
Procédure pas à pas : Utilisation de BatchBlock et BatchedJoinBlock pour améliorer l’efficacitéDécrit comment utiliser le BatchBlock<> </> > classe afin d’améliorer l’efficacité de la base de données insérer des opérations et comment utiliser le BatchedJoinBlock<T1, T2> classe afin de capturer les résultats et les exceptions qui se produisent lorsque le programme lit à partir d’une base de données.</T1, T2>
Procédure pas à pas : Création d’un Type de bloc de flux de données personnaliséMontre deux façons de créer un type de bloc de flux de données qui implémente un comportement personnalisé.
Bibliothèque parallèle de tâches (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.
Afficher: