Programmation asynchrone basée sur les tâchesTask-based Asynchronous Programming

La bibliothèque parallèle de tâches (TPL) est basée sur le concept de tâche, qui représente une opération asynchrone.The Task Parallel Library (TPL) is based on the concept of a task, which represents an asynchronous operation. À certains égards, une tâche ressemble à un thread ou à un élément de travail ThreadPool, mais à un niveau d'abstraction supérieur.In some ways, a task resembles a thread or ThreadPool work item, but at a higher level of abstraction. Le terme parallélisme des tâches fait référence à une ou plusieurs tâches indépendantes qui s’exécutent simultanément.The term task parallelism refers to one or more independent tasks running concurrently. Les tâches présentent deux grands avantages :Tasks provide two primary benefits:

  • Une utilisation plus efficace et évolutive des ressources système.More efficient and more scalable use of system resources.

    En arrière-plan, les tâches sont mises en file d'attente dans le ThreadPool, amélioré au moyen d'algorithmes qui déterminent le nombre de threads (et s'y ajustent) et qui fournissent l'équilibrage de charge afin d'optimiser le débit.Behind the scenes, tasks are queued to the ThreadPool, which has been enhanced with algorithms that determine and adjust to the number of threads and that provide load balancing to maximize throughput. Cela rend les tâches relativement simples et vous permet d’en créer de nombreuses pour un parallélisme affiné.This makes tasks relatively lightweight, and you can create many of them to enable fine-grained parallelism.

  • Davantage de contrôle par programmation qu'avec un thread ou un élément de travail.More programmatic control than is possible with a thread or work item.

    Les tâches et l'infrastructure construites autour de ces algorithmes fournissent un ensemble riche d'API prenant en charge l'attente, l'annulation, les continuations, la gestion fiable des exceptions, l'état détaillé, la planification personnalisée, et bien plus encore.Tasks and the framework built around them provide a rich set of APIs that support waiting, cancellation, continuations, robust exception handling, detailed status, custom scheduling, and more.

Pour ces raisons, la bibliothèque parallèle de tâches est l'API privilégiée pour l'écriture du code multithread, asynchrone et parallèle dans .NET Framework.For both of these reasons, in the .NET Framework, TPL is the preferred API for writing multi-threaded, asynchronous, and parallel code.

Création et exécution implicites de tâchesCreating and running tasks implicitly

La méthode Parallel.Invoke offre un moyen pratique d'exécuter simultanément un nombre d'instructions arbitraires.The Parallel.Invoke method provides a convenient way to run any number of arbitrary statements concurrently. Pour cela, passez un délégué Action pour chaque élément de travail.Just pass in an Action delegate for each item of work. La façon la plus facile de créer ces délégués est d’utiliser des expressions lambda.The easiest way to create these delegates is to use lambda expressions. L’expression lambda peut appeler une méthode nommée ou fournir le code inline.The lambda expression can either call a named method or provide the code inline. L'exemple suivant montre un appel Invoke de base qui crée et démarre deux tâches qui s'exécutent simultanément.The following example shows a basic Invoke call that creates and starts two tasks that run concurrently. La première tâche est représentée par une expression lambda qui appelle une méthode nommée DoSomeWork et la seconde tâche est représentée par une expression lambda qui appelle une méthode nommée DoSomeOtherWork.The first task is represented by a lambda expression that calls a method named DoSomeWork, and the second task is represented by a lambda expression that calls a method named DoSomeOtherWork.

Note

Cette documentation utilise les expressions lambda pour définir les délégués de la bibliothèque parallèle de tâches.This documentation uses lambda expressions to define delegates in TPL. Si les expressions lambda en C# ou Visual Basic ne vous sont pas familières, consultez la page Expressions lambda en PLINQ et dans la bibliothèque parallèle de tâches.If you are not familiar with lambda expressions in C# or Visual Basic, see Lambda Expressions in PLINQ and TPL.

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Parallel.Invoke(Sub() DoSomeWork(), Sub() DoSomeOtherWork())

Note

Le nombre d'instances Task créées en arrière-plan par Invoke n'est pas nécessairement égal au nombre de délégués fournis.The number of Task instances that are created behind the scenes by Invoke is not necessarily equal to the number of delegates that are provided. La bibliothèque parallèle de tâches peut utiliser différentes optimisations, surtout avec un grand nombre de délégués.The TPL may employ various optimizations, especially with large numbers of delegates.

Pour plus d’informations, consultez Comment : utiliser parallel_invoke pour exécuter des opérations parallèles.For more information, see How to: Use Parallel.Invoke to Execute Parallel Operations.

Pour un plus grand contrôle de l'exécution de tâches ou pour retourner une valeur à partir de la tâche, vous devez utiliser les objets Task de manière plus explicite.For greater control over task execution or to return a value from the task, you have to work with Task objects more explicitly.

Création et exécution explicites de tâchesCreating and running tasks explicitly

Une tâche qui ne retourne pas de valeur est représentée par la classe System.Threading.Tasks.Task.A task that does not return a value is represented by the System.Threading.Tasks.Task class. Une tâche qui retourne une valeur est représentée par la classe System.Threading.Tasks.Task<TResult>, qui hérite de Task.A task that returns a value is represented by the System.Threading.Tasks.Task<TResult> class, which inherits from Task. L’objet de tâche gère les détails de l’infrastructure et fournit des méthodes et des propriétés accessibles depuis le thread appelant pendant la durée de vie de la tâche.The task object handles the infrastructure details and provides methods and properties that are accessible from the calling thread throughout the lifetime of the task. Par exemple, vous pouvez accéder à la propriété Status d'une tâche à tout moment pour déterminer si son exécution a commencé, est terminée, a été annulée ou a levé une exception.For example, you can access the Status property of a task at any time to determine whether it has started running, ran to completion, was canceled, or has thrown an exception. Le statut est représenté par une énumération TaskStatus.The status is represented by a TaskStatus enumeration.

Lorsque vous créez une tâche, vous lui donnez un délégué utilisateur qui encapsule le code que la tâche exécutera.When you create a task, you give it a user delegate that encapsulates the code that the task will execute. Le délégué peut être exprimé en tant que délégué nommé, méthode anonyme ou expression lambda.The delegate can be expressed as a named delegate, an anonymous method, or a lambda expression. Les expressions lambda peuvent contenir un appel à une méthode nommée, comme indiqué dans l’exemple suivant.Lambda expressions can contain a call to a named method, as shown in the following example. Notez que l'exemple inclut un appel à la méthode Task.Wait pour garantir que l'exécution de la tâche se termine avant la fin de l'application en mode console.Note that the example includes a call to the Task.Wait method to ensure that the task completes execution before the console mode application ends.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.Name = "Main";

      // Create a task and supply a user delegate by using a lambda expression. 
      Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
      // Start the task.
      taskA.Start();

      // Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                        Thread.CurrentThread.Name);
      taskA.Wait();
   }
}
// The example displays output like the following:
//       Hello from thread 'Main'.
//       Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Thread.CurrentThread.Name = "Main"
        
        ' Create a task and supply a user delegate by using a lambda expression. 
        Dim taskA = New Task(Sub() Console.WriteLine("Hello from taskA."))
        ' Start the task.
        taskA.Start()

        ' Output a message from the calling thread.
        Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name)
        taskA.Wait()
   End Sub
End Module
' The example displays output like the following:
'    Hello from thread 'Main'.
'    Hello from taskA.

Vous pouvez également utiliser les méthodes Task.Run pour créer et lancer une tâche dans une opération.You can also use the Task.Run methods to create and start a task in one operation. Pour gérer la tâche, les méthodes Run utilisent le planificateur de tâches par défaut, quel que soit le planificateur de tâches associé au thread actuel.To manage the task, the Run methods use the default task scheduler, regardless of which task scheduler is associated with the current thread. Les méthodes Run représentent la meilleure façon de créer et de lancer des tâches lorsqu'un plus grand contrôle sur la création et la planification de la tâche n'est pas nécessaire.The Run methods are the preferred way to create and start tasks when more control over the creation and scheduling of the task is not needed.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.Name = "Main";

      // Define and run the task.
      Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));

      // Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name);
      taskA.Wait();
   }
}
// The example displays output like the following:
//       Hello from thread 'Main'.
//       Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Thread.CurrentThread.Name = "Main"
        
        Dim taskA As Task = Task.Run(Sub() Console.WriteLine("Hello from taskA."))

        ' Output a message from the calling thread.
        Console.WriteLine("Hello from thread '{0}'.", 
                          Thread.CurrentThread.Name)
        taskA.Wait()
   End Sub
End Module
' The example displays output like the following:
'    Hello from thread 'Main'.
'    Hello from taskA.

Vous pouvez également utiliser la méthode TaskFactory.StartNew pour créer et lancer une tâche dans une opération.You can also use the TaskFactory.StartNew method to create and start a task in one operation. Utilisez cette méthode quand la création et la planification n'ont pas besoin d'être séparées et que vous avez besoin d'options supplémentaires de création de tâches ou d'utiliser un planificateur spécifique, ou lorsque vous devez obtenir l'état supplémentaire dans la tâche via sa propriété AsyncState, comme indiqué dans l'exemple suivant.Use this method when creation and scheduling do not have to be separated and you require additional task creation options or the use of a specific scheduler, or when you need to pass additional state into the task through its AsyncState property, as shown in the following example.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.Name = "Main";

      // Better: Create and start the task in one operation. 
      Task taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));
      
      // Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                        Thread.CurrentThread.Name);

      taskA.Wait();                  
   }
}
// The example displays output like the following:
//       Hello from thread 'Main'.
//       Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Thread.CurrentThread.Name = "Main"
      
      ' Better: Create and start the task in one operation. 
      Dim taskA = Task.Factory.StartNew(Sub() Console.WriteLine("Hello from taskA."))
      
      ' Output a message from the calling thread.
      Console.WriteLine("Hello from thread '{0}'.", 
                        Thread.CurrentThread.Name)

      taskA.Wait()                  
   End Sub
End Module
' The example displays output like the following:
'       Hello from thread 'Main'.
'       Hello from taskA.

Task et Task<TResult> exposent tous deux une propriété Factory statique qui retourne une instance par défaut de TaskFactory, afin que vous puissiez appeler la méthode en tant que Task.Factory.StartNew().Task and Task<TResult> each expose a static Factory property that returns a default instance of TaskFactory, so that you can call the method as Task.Factory.StartNew(). De plus, dans l'exemple suivant, parce que les tâches sont de type System.Threading.Tasks.Task<TResult>, chacune d'elle a une propriété Task<TResult>.Result publique contenant le résultat du calcul.Also, in the following example, because the tasks are of type System.Threading.Tasks.Task<TResult>, they each have a public Task<TResult>.Result property that contains the result of the computation. Les tâches sont exécutées de façon asynchrone et peuvent se terminer dans n’importe quel ordre.The tasks run asynchronously and may complete in any order. Si la propriété Result est accessible avant la fin du calcul, la propriété bloque le thread appelant jusqu'à ce que la valeur soit disponible.If the Result property is accessed before the computation finishes, the property blocks the calling thread until the value is available.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
        Task<Double>[] taskArray = { Task<Double>.Factory.StartNew(() => DoComputation(1.0)),
                                     Task<Double>.Factory.StartNew(() => DoComputation(100.0)), 
                                     Task<Double>.Factory.StartNew(() => DoComputation(1000.0)) };

        var results = new Double[taskArray.Length];
        Double sum = 0;
        
        for (int i = 0; i < taskArray.Length; i++) {
            results[i] = taskArray[i].Result;
            Console.Write("{0:N1} {1}", results[i], 
                              i == taskArray.Length - 1 ? "= " : "+ ");
            sum += results[i];
        }
        Console.WriteLine("{0:N1}", sum);
   }

   private static Double DoComputation(Double start)
   {
      Double sum = 0;
      for (var value = start; value <= start + 10; value += .1)
         sum += value;

      return sum; 
   }
}
// The example displays the following output:
//        606.0 + 10,605.0 + 100,495.0 = 111,706.0
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
        Dim taskArray() = { Task(Of Double).Factory.StartNew(Function() DoComputation(1.0)),
                            Task(Of Double).Factory.StartNew(Function() DoComputation(100.0)), 
                            Task(Of Double).Factory.StartNew(Function() DoComputation(1000.0)) }

        Dim results(taskArray.Length - 1) As Double
        Dim sum As Double
        
        For i As Integer = 0 To taskArray.Length - 1
            results(i) = taskArray(i).Result
            Console.Write("{0:N1} {1}", results(i), 
                              If(i = taskArray.Length - 1, "= ", "+ "))
            sum += results(i)
        Next
        Console.WriteLine("{0:N1}", sum)
   End Sub
   
   Private Function DoComputation(start As Double) As Double
      Dim sum As Double
      For value As Double = start To start + 10 Step .1
         sum += value
      Next
      Return sum 
   End Function
End Module
' The example displays the following output:
'       606.0 + 10,605.0 + 100,495.0 = 111,706.0

Pour plus d’informations, consultez Comment : retourner une valeur à partir d’une tâche.For more information, see How to: Return a Value from a Task.

Lorsque vous utilisez une expression lambda pour créer le délégué d’une tâche, vous avez accès à toutes les variables qui sont visibles à ce stade dans votre code source.When you use a lambda expression to create a delegate, you have access to all the variables that are visible at that point in your source code. Toutefois, dans certains cas, notamment dans les boucles, une expression lambda ne capture pas la variable comme prévu.However, in some cases, most notably within loops, a lambda doesn't capture the variable as expected. Elle capture uniquement la valeur finale, pas la valeur qui change au cours de chaque itération.It only captures the final value, not the value as it mutates after each iteration. L'exemple de code suivant illustre le problème.The following example illustrates the problem. Il passe un compteur de boucles à une expression lambda qui instancie un objet CustomData et utilise le compteur de boucles comme identificateur de l'objet.It passes a loop counter to a lambda expression that instantiates a CustomData object and uses the loop counter as the object's identifier. Comme le montre la sortie de l'exemple, chaque objet CustomData a un identificateur identique.As the output from the example shows, each CustomData object has an identical identifier.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      // Create the task object by using an Action(Of Object) to pass in the loop
      // counter. This produces an unexpected result.
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj) => {
                                                 var data = new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks}; 
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum);
                                               },
                                              i );
      }
      Task.WaitAll(taskArray);     
   }
}
// The example displays output like the following:
//       Task #10 created at 635116418427727841 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427727841 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427737842 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      ' Create the task object by using an Action(Of Object) to pass in the loop
      ' counter. This produces an unexpected result.
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} 
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum)
                                              End Sub,
                                              i )
      Next
      Task.WaitAll(taskArray)     
   End Sub
End Module
' The example displays output like the following:
'       Task #10 created at 635116418427727841 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427737842 on thread #4.
'       Task #10 created at 635116418427727841 on thread #3.
'       Task #10 created at 635116418427747843 on thread #3.
'       Task #10 created at 635116418427747843 on thread #3.
'       Task #10 created at 635116418427737842 on thread #4.

Vous pouvez accéder à la valeur de chaque itération en fournissant un objet d’état à une tâche via son constructeur.You can access the value on each iteration by providing a state object to a task through its constructor. L'exemple suivant modifie l'exemple précédent en utilisant le compteur de boucles lors de la création de l'objet CustomData qui, à son tour, est passé à l'expression lambda.The following example modifies the previous example by using the loop counter when creating the CustomData object, which, in turn, is passed to the lambda expression. Comme le montre la sortie de l'exemple, chaque objet CustomData possède maintenant un identificateur unique basé sur la valeur du compteur de boucle au moment où l'objet a été instancié.As the output from the example shows, each CustomData object now has a unique identifier based on the value of the loop counter at the time the object was instantiated.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      // Create the task object by using an Action(Of Object) to pass in custom data
      // to the Task constructor. This is useful when you need to capture outer variables
      // from within a loop. 
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
                                                  CustomData data = obj as CustomData;
                                                  if (data == null) 
                                                     return;
                                     
                                                  data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                                  Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum);
                                               },
                                               new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
      }
      Task.WaitAll(taskArray);     
   }
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      ' Create the task object by using an Action(Of Object) to pass in custom data
      ' to the Task constructor. This is useful when you need to capture outer variables
      ' from within a loop. 
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As CustomData = TryCast(obj, CustomData)
                                                 If data Is Nothing Then Return
                                     
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                                 Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
                                                                   data.Name, data.CreationTime, data.ThreadNum)
                                              End Sub,
                                              New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} )
      Next
      Task.WaitAll(taskArray)     
   End Sub
End Module
' The example displays output like the following:
'       Task #0 created at 635116412924597583 on thread #3.
'       Task #1 created at 635116412924607584 on thread #4.
'       Task #3 created at 635116412924607584 on thread #4.
'       Task #4 created at 635116412924607584 on thread #4.
'       Task #2 created at 635116412924607584 on thread #3.
'       Task #6 created at 635116412924607584 on thread #3.
'       Task #5 created at 635116412924607584 on thread #4.
'       Task #8 created at 635116412924607584 on thread #4.
'       Task #7 created at 635116412924607584 on thread #3.
'       Task #9 created at 635116412924607584 on thread #4.

Cet état est passé comme argument au délégué de tâche et est accessible dans l'objet de tâche à l'aide de la propriété Task.AsyncState.This state is passed as an argument to the task delegate, and it can be accessed from the task object by using the Task.AsyncState property. L'exemple suivant est une variante de l'exemple précédent.The following example is a variation on the previous example. Il utilise la propriété AsyncState pour afficher des informations sur les objets CustomData passés à l'expression lambda.It uses the AsyncState property to display information about the CustomData objects passed to the lambda expression.

using System;
using System.Threading;
using System.Threading.Tasks;

class CustomData
{
   public long CreationTime;
   public int Name; 
   public int ThreadNum;
}

public class Example
{
   public static void Main()
   {
      Task[] taskArray = new Task[10];
      for (int i = 0; i < taskArray.Length; i++) {
         taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
                                                  CustomData data = obj as CustomData;
                                                  if (data == null) 
                                                     return;
                                     
                                                  data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
                                               },
                                               new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
      }
      Task.WaitAll(taskArray);     
      foreach (var task in taskArray) {
         var data = task.AsyncState as CustomData;
         if (data != null)
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum);
      }                     
   }
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks

Class CustomData
   Public CreationTime As Long
   Public Name As Integer
   Public ThreadNum As Integer
End Class

Module Example
   Public Sub Main()
      Dim taskArray(9) As Task
      For i As Integer = 0 To taskArray.Length - 1
         taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
                                                 Dim data As CustomData = TryCast(obj, CustomData)
                                                 If data Is Nothing Then Return
                                     
                                                 data.ThreadNum = Thread.CurrentThread.ManagedThreadId
                                              End Sub,
                                              New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks} )
      Next
      Task.WaitAll(taskArray)     

      For Each task In taskArray
         Dim data = TryCast(task.AsyncState, CustomData)
         If data IsNot Nothing Then
            Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
                              data.Name, data.CreationTime, data.ThreadNum)
         End If
      Next
   End Sub
End Module
' The example displays output like the following:
'    Task #0 created at 635116451245250515, ran on thread #3, RanToCompletion
'    Task #1 created at 635116451245270515, ran on thread #4, RanToCompletion
'    Task #2 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #3 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #4 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #5 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #6 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #7 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #8 created at 635116451245270515, ran on thread #3, RanToCompletion
'    Task #9 created at 635116451245270515, ran on thread #3, RanToCompletion

ID de tâcheTask ID

Chaque tâche reçoit un ID d'entier qui l'identifie de façon unique dans un domaine d'application et peut être accessible à l'aide de la propriété Task.Id.Every task receives an integer ID that uniquely identifies it in an application domain and can be accessed by using the Task.Id property. L’ID est utile pour la consultation des informations de tâche dans les fenêtres Piles parallèles et Tâches du débogueur Visual Studio.The ID is useful for viewing task information in the Visual Studio debugger Parallel Stacks and Tasks windows. L’ID est créé de manière différée, ce qui signifie qu’il n’est pas créé tant que cela n’est pas demandé ; par conséquent, une tâche peut avoir un ID différent à chaque exécution du programme.The ID is lazily created, which means that it isn't created until it is requested; therefore, a task may have a different ID every time the program is run. Pour plus d’informations sur l’affichage des ID de tâche dans le débogueur, consultez Utilisation de la fenêtre Tâches et Utilisation de la fenêtre Piles parallèles.For more information about how to view task IDs in the debugger, see Using the Tasks Window and Using the Parallel Stacks Window.

Options de création de tâchesTask Creation Options

La plupart des API qui créent des tâches fournissent des surcharges qui acceptent un paramètre TaskCreationOptions.Most APIs that create tasks provide overloads that accept a TaskCreationOptions parameter. En spécifiant l’une de ces options, vous indiquez au planificateur de tâches la manière de planifier la tâche dans le pool de threads.By specifying one of these options, you tell the task scheduler how to schedule the task on the thread pool. Le tableau suivant répertorie les différentes options de création de tâches.The following table lists the various task creation options.

Valeur du paramètre TaskCreationOptionsTaskCreationOptions parameter value DescriptionDescription
None Valeur par défaut lorsqu'aucune option n'est spécifiée.The default when no option is specified. Le planificateur utilise ses méthodes heuristiques par défaut pour planifier la tâche.The scheduler uses its default heuristics to schedule the task.
PreferFairness Spécifie que la tâche doit être planifiée afin que les tâches créées précédemment soient susceptibles d’être exécutées plus tôt et que les tâches créées ultérieurement soient susceptibles d’être exécutées plus tard.Specifies that the task should be scheduled so that tasks created sooner will be more likely to be executed sooner, and tasks created later will be more likely to execute later.
LongRunning Spécifie que la tâche représente une opération de longue durée.Specifies that the task represents a long-running operation.
AttachedToParent Spécifie qu’une tâche doit être créée en tant qu’enfant attaché à la tâche actuelle, s’il en existe une.Specifies that a task should be created as an attached child of the current task, if one exists. Pour plus d’informations, consultez Tâches enfants attachées et détachées.For more information, see Attached and Detached Child Tasks.
DenyChildAttach Indique que si une tâche interne spécifie l'option AttachedToParent, cette tâche ne sera pas une tâche enfant attachée.Specifies that if an inner task specifies the AttachedToParent option, that task will not become an attached child task.
HideScheduler Spécifie que le planificateur de tâches pour les tâches créées en appelant des méthodes comme TaskFactory.StartNew ou Task<TResult>.ContinueWith à partir d'une tâche particulière est le planificateur par défaut au lieu du planificateur sur lequel cette tâche s'exécute.Specifies that the task scheduler for tasks created by calling methods like TaskFactory.StartNew or Task<TResult>.ContinueWith from within a particular task is the default scheduler instead of the scheduler on which this task is running.

Les options peuvent être combinées avec une opération de bits OR.The options may be combined by using a bitwise OR operation. L'exemple suivant montre une tâche avec les options LongRunning et PreferFairness.The following example shows a task that has the LongRunning and PreferFairness option.

var task3 = new Task(() => MyLongRunningMethod(),
                    TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
task3.Start();

Dim task3 = New Task(Sub() MyLongRunningMethod(),
                        TaskCreationOptions.LongRunning Or TaskCreationOptions.PreferFairness)
task3.Start()

Tâches, threads et cultureTasks, threads, and culture

Chaque thread possède une culture associée et une culture d'interface utilisateur, respectivement définies par les propriétés Thread.CurrentCulture et Thread.CurrentUICulture.Each thread has an associated culture and UI culture, which is defined by the Thread.CurrentCulture and Thread.CurrentUICulture properties, respectively. La culture d'un thread est utilisée dans des opérations telles que la mise en forme, l'analyse, le tri et la comparaison de chaînes.A thread's culture is used in such operations as formatting, parsing, sorting, and string comparison. La culture d'interface utilisateur d'un thread est utilisée dans la recherche de ressources.A thread's UI culture is used in resource lookup. En règle générale, sauf si vous spécifiez une culture par défaut pour tous les threads dans un domaine d'application à l'aide des propriétés CultureInfo.DefaultThreadCurrentCulture et CultureInfo.DefaultThreadCurrentUICulture, la culture par défaut et la culture d'interface utilisateur d'un thread sont définies par la culture du système.Ordinarily, unless you specify a default culture for all the threads in an application domain by using the CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture properties, the default culture and UI culture of a thread is defined by the system culture. Si vous définissez explicitement la culture d'un thread et lancez un nouveau thread, ce dernier n'hérite pas de la culture du thread appelant ; au lieu de cela, sa culture est la culture du système par défaut.If you explicitly set a thread's culture and launch a new thread, the new thread does not inherit the culture of the calling thread; instead, its culture is the default system culture. Le modèle de programmation basé sur les tâches pour les applications qui ciblent des versions du .NET Framework antérieures à .NET Framework 4.6.NET Framework 4.6 respecte cette pratique.The task-based programming model for apps that target versions of the .NET Framework prior to .NET Framework 4.6.NET Framework 4.6 adhere to this practice.

Important

Notez que la culture du thread appelant dans le cadre du contexte d’une tâche s’applique aux applications qui ciblent le .NET Framework 4.6.NET Framework 4.6, et non celles qui s’exécutent sous le .NET Framework 4.6.NET Framework 4.6.Note that the calling thread's culture as part of a task's context applies to apps that target the .NET Framework 4.6.NET Framework 4.6, not apps that run under the .NET Framework 4.6.NET Framework 4.6. Vous pouvez cibler une version particulière du .NET Framework quand vous créez votre projet dans Visual Studio en sélectionnant une version dans la liste déroulante située en haut de la boîte de dialogue Nouveau projet. Sinon, en dehors de Visual Studio, vous pouvez utiliser l’attribut TargetFrameworkAttribute.You can target a particular version of the .NET Framework when you create your project in Visual Studio by selecting that version from the dropdown list at the top of the New Project dialog box, or outside of Visual Studio you can use the TargetFrameworkAttribute attribute. Pour les applications qui ciblent des versions du .NET Framework antérieures au .NET Framework 4.6.NET Framework 4.6, ou qui ne ciblent pas une version spécifique du .NET Framework, la culture d'une tâche demeure déterminée par la culture du thread sur lequel la tâche s'exécute.For apps that target versions of the .NET Framework prior to the .NET Framework 4.6.NET Framework 4.6, or that do not target a specific version of the .NET Framework, a task's culture continues to be determined by the culture of the thread on which it runs.

À compter des applications qui ciblent le .NET Framework 4.6.NET Framework 4.6, la culture du thread appelant est héritée par chaque tâche, même si la tâche s'exécute de façon asynchrone sur un thread de pool de threads.Starting with apps that target the .NET Framework 4.6.NET Framework 4.6, the calling thread's culture is inherited by each task, even if the task runs asynchronously on a thread pool thread.

L'exemple suivant illustre cette situation de façon simple.The following example provides a simple illustration. Il utilise l'attribut TargetFrameworkAttribute pour cibler le .NET Framework 4.6.NET Framework 4.6 et définit la culture actuelle de l'application sur français (France) ou, si français (France) est déjà la culture actuelle, sur anglais (États-Unis).It uses the TargetFrameworkAttribute attribute to target the .NET Framework 4.6.NET Framework 4.6 and changes the app's current culture to either French (France) or, if French (France) is already the current culture, English (United States). Il appelle ensuite un délégué nommé formatDelegate qui retourne des nombres mis en forme en tant que valeurs de devise dans la nouvelle culture.It then invokes a delegate named formatDelegate that returns some numbers formatted as currency values in the new culture. Que le délégué exécute une tâche de manière synchrone ou asynchrone, il retourne le résultat attendu, car la culture du thread appelant est héritée par la tâche asynchrone.Note that whether the delegate as a task either synchronously or asynchronously, it returns the expected result because the culture of the calling thread is inherited by the asynchronous task.

using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;

[assembly:TargetFramework(".NETFramework,Version=v4.6")]

public class Example
{
   
   public static void Main()
   {
       decimal[] values = { 163025412.32m, 18905365.59m };
       string formatString = "C2";
       Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
                                                                           CultureInfo.CurrentCulture.Name,
                                                                           Thread.CurrentThread.ManagedThreadId);
                                             foreach (var value in values)
                                                output += String.Format("{0}   ", value.ToString(formatString));
                                                   
                                             output += Environment.NewLine;
                                             return output;
                                           };
       
       Console.WriteLine("The example is running on thread {0}", 
                         Thread.CurrentThread.ManagedThreadId);
       // Make the current culture different from the system culture.
       Console.WriteLine("The current culture is {0}", 
                         CultureInfo.CurrentCulture.Name);
       if (CultureInfo.CurrentCulture.Name == "fr-FR")
          Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
       else
          Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");

       Console.WriteLine("Changed the current culture to {0}.\n",
                         CultureInfo.CurrentCulture.Name);
       
       // Execute the delegate synchronously.
       Console.WriteLine("Executing the delegate synchronously:");
       Console.WriteLine(formatDelegate());
       
       // Call an async delegate to format the values using one format string.
       Console.WriteLine("Executing a task asynchronously:"); 
       var t1 = Task.Run(formatDelegate);
       Console.WriteLine(t1.Result);
       
       Console.WriteLine("Executing a task synchronously:");
       var t2 = new Task<String>(formatDelegate); 
       t2.RunSynchronously();
       Console.WriteLine(t2.Result);
   }
}
// The example displays the following output:
//         The example is running on thread 1
//         The current culture is en-US
//         Changed the current culture to fr-FR.
//
//         Executing the delegate synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task asynchronously:
//         Formatting using the fr-FR culture on thread 3.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
// If the TargetFrameworkAttribute statement is removed, the example
// displays the following output:
//          The example is running on thread 1
//          The current culture is en-US
//          Changed the current culture to fr-FR.
//
//          Executing the delegate synchronously:
//          Formatting using the fr-FR culture on thread 1.
//          163 025 412,32 €   18 905 365,59 €
//
//          Executing a task asynchronously:
//          Formatting using the en-US culture on thread 3.
//          $163,025,412.32   $18,905,365.59
//
//          Executing a task synchronously:
//          Formatting using the fr-FR culture on thread 1.
//          163 025 412,32 €   18 905 365,59 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks

<Assembly:TargetFramework(".NETFramework,Version=v4.6")>

Module Example
   Public Sub Main()
       Dim values() As Decimal = { 163025412.32d, 18905365.59d }
       Dim formatString As String = "C2"
       Dim formatDelegate As Func(Of String) = Function()
                                                  Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
                                                                                       CultureInfo.CurrentCulture.Name,
                                                                                       Thread.CurrentThread.ManagedThreadId)
                                                  output += Environment.NewLine
                                                  For Each value In values
                                                     output += String.Format("{0}   ", value.ToString(formatString))
                                                  Next 
                                                  output += Environment.NewLine
                                                  Return output
                                               End Function
       
       Console.WriteLine("The example is running on thread {0}", 
                         Thread.CurrentThread.ManagedThreadId)
       ' Make the current culture different from the system culture.
       Console.WriteLine("The current culture is {0}", 
                         CultureInfo.CurrentCulture.Name)
       If CultureInfo.CurrentCulture.Name = "fr-FR" Then
          Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
       Else
          Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
       End If
       Console.WriteLine("Changed the current culture to {0}.",
                         CultureInfo.CurrentCulture.Name)
       Console.WriteLine()                  
       
       ' Execute the delegate synchronously.
       Console.WriteLine("Executing the delegate synchronously:")
       Console.WriteLine(formatDelegate())
       
       ' Call an async delegate to format the values using one format string.
       Console.WriteLine("Executing a task asynchronously:") 
       Dim t1 = Task.Run(formatDelegate)
       Console.WriteLine(t1.Result)
       
       Console.WriteLine("Executing a task synchronously:")
       Dim t2 = New Task(Of String)(formatDelegate) 
       t2.RunSynchronously()
       Console.WriteLine(t2.Result)
   End Sub
End Module
' The example displays the following output:
'          The example is running on thread 1
'          The current culture is en-US
'          Changed the current culture to fr-FR.
'
'          Executing the delegate synchronously:
'          Formatting Imports the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task asynchronously:
'          Formatting Imports the fr-FR culture on thread 3.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task synchronously:
'          Formatting Imports the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
' If the TargetFrameworkAttribute statement is removed, the example
' displays the following output:
'          The example is running on thread 1
'          The current culture is en-US
'          Changed the current culture to fr-FR.
'
'          Executing the delegate synchronously:
'          Formatting using the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €
'
'          Executing a task asynchronously:
'          Formatting using the en-US culture on thread 3.
'          $163,025,412.32   $18,905,365.59
'
'          Executing a task synchronously:
'          Formatting using the fr-FR culture on thread 1.
'          163 025 412,32 €   18 905 365,59 €

Si vous utilisez Visual Studio, vous pouvez omettre l'attribut TargetFrameworkAttribute. Pour cela, vous devez sélectionner le .NET Framework 4.6 comme cible au moment de la création du projet dans la boîte de dialogue Nouveau projet.If you are using Visual Studio, you can omit the TargetFrameworkAttribute attribute and instead select the .NET Framework 4.6 as the target when you create the project in the New Project dialog.

Pour la sortie qui reflète le comportement des applications ciblant des versions du .NET Framework antérieures à .NET Framework 4.6.NET Framework 4.6, supprimez l'attribut TargetFrameworkAttribute du code source.For output that reflects the behavior of apps the target versions of the .NET Framework prior to .NET Framework 4.6.NET Framework 4.6, remove the TargetFrameworkAttribute attribute from the source code. La sortie reflète les conventions de mise en forme de la culture du système par défaut, pas de la culture du thread appelant.The output will reflect the formatting conventions of the default system culture, not the culture of the calling thread.

Pour plus d'informations sur les tâches asynchrones et la culture, consultez la section « Culture et opérations asynchrones basées sur les tâches » dans la rubrique CultureInfo.For more information on asynchronous tasks and culture, see the "Culture and asynchronous task-based operations" section in the CultureInfo topic.

Création de continuations de tâchesCreating task continuations

Les méthodes Task.ContinueWith et Task<TResult>.ContinueWith vous permettent de spécifier une tâche à démarrer lorsque l’antécédent est terminé.The Task.ContinueWith and Task<TResult>.ContinueWith methods let you specify a task to start when the antecedent task finishes. Une référence à la tâche antécédente est passée au délégué de la tâche de continuation afin qu'il puisse examiner l'état de la tâche antécédente et, en récupérant la valeur de la propriété Task<TResult>.Result, utiliser la sortie de l'antécédent comme entrée pour la continuation.The delegate of the continuation task is passed a reference to the antecedent task so that it can examine the antecedent task's status and, by retrieving the value of the Task<TResult>.Result property, can use the output of the antecedent as input for the continuation.

Dans l'exemple suivant, la tâche getData est démarrée par un appel à la méthode TaskFactory.StartNew<TResult>(Func<TResult>).In the following example, the getData task is started by a call to the TaskFactory.StartNew<TResult>(Func<TResult>) method. La tâche processData démarre automatiquement lorsque getData est terminé, et displayData commence lorsque processData est terminé.The processData task is started automatically when getData finishes, and displayData is started when processData finishes. getData produit un tableau d'entiers, accessible à la tâche processData via la propriété getData de la tâche Task<TResult>.Result.getData produces an integer array, which is accessible to the processData task through the getData task's Task<TResult>.Result property. La tâche processData traite ce tableau et retourne un résultat dont le type est déduit du type de retour de l'expression lambda passée à la méthode Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>).The processData task processes that array and returns a result whose type is inferred from the return type of the lambda expression passed to the Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>) method. La tâche displayData s'exécute automatiquement lorsque processData est terminé, et l'objet Tuple<T1,T2,T3> retourné par l'expression lambda processData est accessible à la tâche displayData via la propriété processData de la tâche Task<TResult>.Result.The displayData task executes automatically when processData finishes, and the Tuple<T1,T2,T3> object returned by the processData lambda expression is accessible to the displayData task through the processData task's Task<TResult>.Result property. La tâche displayData prend le résultat de la tâche processData et produit un résultat dont le type est déduit de façon semblable et mis à disposition du programme dans la propriété Result.The displayData task takes the result of the processData task and produces a result whose type is inferred in a similar manner and which is made available to the program in the Result property.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {                         
      var getData = Task.Factory.StartNew(() => { 
                                             Random rnd = new Random(); 
                                             int[] values = new int[100];
                                             for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                values[ctr] = rnd.Next();

                                             return values;
                                          } );  
      var processData = getData.ContinueWith((x) => {
                                                int n = x.Result.Length;
                                                long sum = 0;
                                                double mean;
                                  
                                                for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                                   sum += x.Result[ctr];

                                                mean = sum / (double) n;
                                                return Tuple.Create(n, sum, mean);
                                             } ); 
      var displayData = processData.ContinueWith((x) => {
                                                    return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                         x.Result.Item1, x.Result.Item2, 
                                                                         x.Result.Item3);
                                                 } );                         
      Console.WriteLine(displayData.Result);
   }
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim getData = Task.Factory.StartNew(Function() 
                                             Dim rnd As New Random()
                                             Dim values(99) As Integer
                                             For ctr = 0 To values.GetUpperBound(0)
                                                values(ctr) = rnd.Next()
                                             Next
                                             Return values
                                          End Function)  
      Dim processData = getData.ContinueWith(Function(x)
                                                Dim n As Integer = x.Result.Length
                                                Dim sum As Long
                                                Dim mean As Double
                                  
                                                For ctr = 0 To x.Result.GetUpperBound(0)
                                                   sum += x.Result(ctr)
                                                Next
                                                mean = sum / n
                                                Return Tuple.Create(n, sum, mean)
                                             End Function) 
      Dim displayData = processData.ContinueWith(Function(x)
                                                    Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                                         x.Result.Item1, x.Result.Item2, 
                                                                         x.Result.Item3)
                                                 End Function)                         
      Console.WriteLine(displayData.Result)
   End Sub                        
End Module
' The example displays output like the following:
'   N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

Comme Task.ContinueWith est une méthode d'instance, vous pouvez concaténer les appels de méthode ensemble au lieu d'instancier un objet Task<TResult> pour chaque antécédent.Because Task.ContinueWith is an instance method, you can chain method calls together instead of instantiating a Task<TResult> object for each antecedent task. L'exemple suivant est fonctionnellement identique à l'exemple précédent, sauf qu'il chaîne ensemble les appels à la méthode Task.ContinueWith.The following example is functionally identical to the previous example, except that it chains together calls to the Task.ContinueWith method. Notez que l'objet Task<TResult> retourné par la chaîne d'appels de méthode est la tâche de continuation finale.Note that the Task<TResult> object returned by the chain of method calls is the final continuation task.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {                         
      var displayData = Task.Factory.StartNew(() => { 
                                                 Random rnd = new Random(); 
                                                 int[] values = new int[100];
                                                 for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
                                                    values[ctr] = rnd.Next();

                                                 return values;
                                              } ).  
                        ContinueWith((x) => {
                                        int n = x.Result.Length;
                                        long sum = 0;
                                        double mean;
                                  
                                        for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
                                           sum += x.Result[ctr];

                                        mean = sum / (double) n;
                                        return Tuple.Create(n, sum, mean);
                                     } ). 
                        ContinueWith((x) => {
                                        return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                             x.Result.Item1, x.Result.Item2, 
                                                             x.Result.Item3);
                                     } );                         
      Console.WriteLine(displayData.Result);
   }
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim displayData = Task.Factory.StartNew(Function() 
                                                 Dim rnd As New Random()
                                                 Dim values(99) As Integer
                                                 For ctr = 0 To values.GetUpperBound(0)
                                                    values(ctr) = rnd.Next()
                                                 Next
                                                 Return values
                                              End Function). _  
                        ContinueWith(Function(x)
                                        Dim n As Integer = x.Result.Length
                                        Dim sum As Long
                                        Dim mean As Double
                                  
                                        For ctr = 0 To x.Result.GetUpperBound(0)
                                           sum += x.Result(ctr)
                                        Next
                                        mean = sum / n
                                        Return Tuple.Create(n, sum, mean)
                                     End Function). _ 
                        ContinueWith(Function(x)
                                        Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
                                                             x.Result.Item1, x.Result.Item2,  
                                                             x.Result.Item3)
                                     End Function)                         
      Console.WriteLine(displayData.Result)
   End Sub                        
End Module
' The example displays output like the following:
'   N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

Les méthodes ContinueWhenAll et ContinueWhenAny vous permettent de continuer avec plusieurs tâches.The ContinueWhenAll and ContinueWhenAny methods enable you to continue from multiple tasks.

Pour plus d’informations, consultez Chaînage des tâches à l’aide de tâches de continuation.For more information, see Chaining Tasks by Using Continuation Tasks.

Création de tâches enfants détachéesCreating detached child tasks

Lorsque le code utilisateur qui s'exécute dans une tâche crée une tâche sans spécifier l'option AttachedToParent, la nouvelle tâche n'est pas synchronisée avec la tâche parent externe.When user code that is running in a task creates a new task and does not specify the AttachedToParent option, the new task is not synchronized with the parent task in any special way. Ce type de tâche non synchronisée est appelé tâche imbriquée détachée ou tâche enfant détachée.This type of non-synchronized task is called a detached nested task or detached child task. L’exemple suivant montre une tâche qui crée une tâche enfant détachée.The following example shows a task that creates one detached child task.

var outer = Task.Factory.StartNew(() =>
{
    Console.WriteLine("Outer task beginning.");

    var child = Task.Factory.StartNew(() =>
    {
        Thread.SpinWait(5000000);
        Console.WriteLine("Detached task completed.");
    });

});

outer.Wait();
Console.WriteLine("Outer task completed.");
// The example displays the following output:
//    Outer task beginning.
//    Outer task completed.
//    Detached task completed.
Dim outer = Task.Factory.StartNew(Sub()
                                      Console.WriteLine("Outer task beginning.")
                                      Dim child = Task.Factory.StartNew(Sub()
                                                                            Thread.SpinWait(5000000)
                                                                            Console.WriteLine("Detached task completed.")
                                                                        End Sub)
                                  End Sub)
outer.Wait()
Console.WriteLine("Outer task completed.")
' The example displays the following output:
'     Outer task beginning.
'     Outer task completed.
'    Detached child completed.

Notez que la tâche parent n’attend pas que la tâche enfant détachée soit terminée.Note that the parent task does not wait for the detached child task to finish.

Création de tâches enfantsCreating child tasks

Lorsque le code utilisateur qui s’exécute dans une tâche crée une tâche avec l’option AttachedToParent, la nouvelle tâche est une tâche enfant attachée de la tâche d’origine, appelée tâche parent.When user code that is running in a task creates a task with the AttachedToParent option, the new task is known as a attached child task of the parent task. Vous pouvez utiliser l'option AttachedToParent pour exprimer le parallélisme des tâches structuré, car la tâche parent attend implicitement que toutes les tâches enfants attachées soient terminées.You can use the AttachedToParent option to express structured task parallelism, because the parent task implicitly waits for all attached child tasks to finish. L'exemple suivant affiche une tâche parent qui crée dix tâches enfants attachées.The following example shows a parent task that creates ten attached child tasks. Notez que l'exemple appelle la méthode Task.Wait pour attendre la fin de la tâche parente, il ne doit pas explicitement attendre la fin des tâches enfants attachées.Note that although the example calls the Task.Wait method to wait for the parent task to finish, it does not have to explicitly wait for the attached child tasks to complete.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var parent = Task.Factory.StartNew(() => {
                      Console.WriteLine("Parent task beginning.");
                      for (int ctr = 0; ctr < 10; ctr++) {
                         int taskNo = ctr;
                         Task.Factory.StartNew((x) => {
                                                  Thread.SpinWait(5000000);
                                                  Console.WriteLine("Attached child #{0} completed.", 
                                                                    x);
                                               },
                                               taskNo, TaskCreationOptions.AttachedToParent);
                      }
                   });

      parent.Wait();
      Console.WriteLine("Parent task completed.");
   }
}
// The example displays output like the following:
//       Parent task beginning.
//       Attached child #9 completed.
//       Attached child #0 completed.
//       Attached child #8 completed.
//       Attached child #1 completed.
//       Attached child #7 completed.
//       Attached child #2 completed.
//       Attached child #6 completed.
//       Attached child #3 completed.
//       Attached child #5 completed.
//       Attached child #4 completed.
//       Parent task completed.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim parent = Task.Factory.StartNew(Sub()
                                            Console.WriteLine("Parent task beginning.")
                                            For ctr As Integer = 0 To 9
                                               Dim taskNo As Integer = ctr
                                               Task.Factory.StartNew(Sub(x)
                                                                        Thread.SpinWait(5000000)
                                                                        Console.WriteLine("Attached child #{0} completed.", 
                                                                                          x)
                                                                     End Sub,
                                                                     taskNo, TaskCreationOptions.AttachedToParent)
                                            Next
                                         End Sub)
      parent.Wait()
      Console.WriteLine("Parent task completed.")
   End Sub
End Module   
' The example displays output like the following:
'       Parent task beginning.
'       Attached child #9 completed.
'       Attached child #0 completed.
'       Attached child #8 completed.
'       Attached child #1 completed.
'       Attached child #7 completed.
'       Attached child #2 completed.
'       Attached child #6 completed.
'       Attached child #3 completed.
'       Attached child #5 completed.
'       Attached child #4 completed.
'       Parent task completed.

Une tâche parent peut utiliser l'option TaskCreationOptions.DenyChildAttach pour empêcher d'autres tâches de s'attacher à la tâche parent.A parent task can use the TaskCreationOptions.DenyChildAttach option to prevent other tasks from attaching to the parent task. Pour plus d’informations, consultez Tâches enfants attachées et détachées.For more information, see Attached and Detached Child Tasks.

Attente de fin d’exécution de tâchesWaiting for tasks to finish

Les types System.Threading.Tasks.Task et System.Threading.Tasks.Task<TResult> fournissent plusieurs surcharges des méthodes Task.Wait, System.Threading.Tasks.Task.Wait qui vous permettent d’attendre qu’une tâche soit terminée.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> types provide several overloads of the Task.Wait and System.Threading.Tasks.Task.Wait methods that enable you to wait for a task to finish. De plus, les surcharges des méthodes statiques Task.WaitAll et Task.WaitAny vous permettent d'attendre que certaines ou toutes les tâches soient terminées.In addition, overloads of the static Task.WaitAll and Task.WaitAny methods let you wait for any or all of an array of tasks to finish.

En général, il est nécessaire d’attendre une tâche pour l’une des raisons suivantes :Typically, you would wait for a task for one of these reasons:

  • Le thread principal dépend du résultat final calculé par une tâche.The main thread depends on the final result computed by a task.

  • Vous devez gérer les exceptions pouvant être levées depuis la tâche.You have to handle exceptions that might be thrown from the task.

  • L'application peut se fermer avant que l'exécution de toutes les tâches ne soit terminée.The application may terminate before all tasks have completed execution. Par exemple, les applications de console s'arrêtent dès que l'intégralité du code synchrone dans Main (point d'entrée de l'application) est exécutée.For example, console applications will terminate as soon as all synchronous code in Main (the application entry point) has executed.

L’exemple suivant affiche le modèle de base qui n’implique pas la gestion des exceptions.The following example shows the basic pattern that does not involve exception handling.

Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);

// Continue on this thread...
Dim tasks() =
{
    Task.Factory.StartNew(Sub() MethodA()),
    Task.Factory.StartNew(Sub() MethodB()),
    Task.Factory.StartNew(Sub() MethodC())
}

' Block until all tasks complete.
Task.WaitAll(tasks)

' Continue on this thread...

Pour obtenir un exemple illustrant la gestion des exceptions, consultez Gestion des exceptions.For an example that shows exception handling, see Exception Handling.

Certaines surcharges vous permettent de spécifier un délai d'attente, et d'autres prennent un CancellationToken supplémentaire en tant que paramètre d'entrée, afin que l'attente puisse être annulée soit par programmation, soit en réponse à l'entrée utilisateur.Some overloads let you specify a time-out, and others take an additional CancellationToken as an input parameter, so that the wait itself can be canceled either programmatically or in response to user input.

Lorsque vous attendez une tâche, vous attendez implicitement tous les enfants de cette tâche créés à l'aide de l'option TaskCreationOptions.AttachedToParent.When you wait for a task, you implicitly wait for all children of that task that were created by using the TaskCreationOptions.AttachedToParent option. Task.Wait est retourné immédiatement si la tâche est déjà terminée.Task.Wait returns immediately if the task has already completed. Toutes les exceptions déclenchées par une tâche seront levées par une méthode Task.Wait, même si la méthode Task.Wait a été appelée une fois la tâche terminée.Any exceptions raised by a task will be thrown by a Task.Wait method, even if the Task.Wait method was called after the task completed.

Composition des tâchesComposing tasks

Les classes Task et Task<TResult> fournissent plusieurs méthodes qui peuvent vous aider à composer plusieurs tâches pour implémenter des modèles courants et améliorer l’utilisation des fonctionnalités de langage asynchrones fournies par C#, Visual Basic et F#.The Task and Task<TResult> classes provide several methods that can help you compose multiple tasks to implement common patterns and to better use the asynchronous language features that are provided by C#, Visual Basic, and F#. Cette section décrit les méthodes WhenAll, WhenAny, Delay et FromResult.This section describes the WhenAll, WhenAny, Delay, and FromResult methods.

Task.WhenAllTask.WhenAll

La méthode Task.WhenAll attend de façon asynchrone que plusieurs objets Task ou Task<TResult> se terminent.The Task.WhenAll method asynchronously waits for multiple Task or Task<TResult> objects to finish. Elle fournit des versions surchargées qui vous permettent d'attendre des ensembles de tâches non-uniformes.It provides overloaded versions that enable you to wait for non-uniform sets of tasks. Par exemple, vous pouvez attendre que plusieurs objets Task et Task<TResult> soient terminés à partir d'un appel de méthode.For example, you can wait for multiple Task and Task<TResult> objects to complete from one method call.

Task.WhenAnyTask.WhenAny

La méthode Task.WhenAny attend de façon asynchrone qu'un des objets Task ou Task<TResult> se termine.The Task.WhenAny method asynchronously waits for one of multiple Task or Task<TResult> objects to finish. À l'instar de la méthode Task.WhenAll, cette méthode fournit des versions surchargées qui vous permettent d'attendre des jeux de tâches non-uniformes.As in the Task.WhenAll method, this method provides overloaded versions that enable you to wait for non-uniform sets of tasks. La méthode WhenAny est spécialement utile dans les scénarios suivants.The WhenAny method is especially useful in the following scenarios.

  • Opérations redondantes.Redundant operations. Considérez un algorithme ou une opération pouvant être exécutée plusieurs façons.Consider an algorithm or operation that can be performed in many ways. Vous pouvez utiliser la méthode WhenAny pour sélectionner l'opération qui se termine en premier et annuler les opérations restantes.You can use the WhenAny method to select the operation that finishes first and then cancel the remaining operations.

  • Opérations entrelacées.Interleaved operations. Vous pouvez démarrer plusieurs opérations qui doivent toutes se terminer et utiliser la méthode WhenAny pour traiter les résultats à mesure que chaque opération se termine.You can start multiple operations that must all finish and use the WhenAny method to process results as each operation finishes. Lorsqu’une opération se termine, vous pouvez démarrer une ou plusieurs autres tâches.After one operation finishes, you can start one or more additional tasks.

  • Opérations limitées.Throttled operations. Vous pouvez utiliser la méthode WhenAny pour étendre le scénario précédent en limitant le nombre d'opérations simultanées.You can use the WhenAny method to extend the previous scenario by limiting the number of concurrent operations.

  • Opérations expirées.Expired operations. Vous pouvez utiliser la méthode WhenAny pour sélectionner entre une ou plusieurs tâches et une tâche qui se termine après une heure spécifique, telle qu'une tâche retournée par la méthode Delay.You can use the WhenAny method to select between one or more tasks and a task that finishes after a specific time, such as a task that is returned by the Delay method. La méthode Delay est décrite dans la section suivante.The Delay method is described in the following section.

Task.DelayTask.Delay

La méthode Task.Delay produit un objet Task qui se termine après le délai spécifié.The Task.Delay method produces a Task object that finishes after the specified time. Vous pouvez utiliser cette méthode pour générer des boucles qui, occasionnellement, sondent les données, introduisent des délais, diffèrent la gestion des entrées d'utilisateur pendant une durée prédéterminé, et ainsi de suite.You can use this method to build loops that occasionally poll for data, introduce time-outs, delay the handling of user input for a predetermined time, and so on.

Task(T).FromResultTask(T).FromResult

En utilisant la méthode Task.FromResult, vous pouvez créer un objet Task<TResult> qui contient un résultat précalculé.By using the Task.FromResult method, you can create a Task<TResult> object that holds a pre-computed result. Cette méthode est utile lorsque vous exécutez une opération asynchrone qui retourne un objet Task<TResult>, et que le résultat de cet objet Task<TResult> est déjà calculé.This method is useful when you perform an asynchronous operation that returns a Task<TResult> object, and the result of that Task<TResult> object is already computed. Pour obtenir un exemple qui utilise FromResult pour récupérer les résultats des opérations de téléchargement asynchrones qui sont conservées dans un cache, consultez Procédure : création de tâches précalculées.For an example that uses FromResult to retrieve the results of asynchronous download operations that are held in a cache, see How to: Create Pre-Computed Tasks.

Gestion des exceptions des tâchesHandling exceptions in tasks

Lorsqu'une tâche lève une ou plusieurs exceptions, les exceptions sont encapsulées dans une exception AggregateException.When a task throws one or more exceptions, the exceptions are wrapped in an AggregateException exception. Cette exception est propagée vers le thread joint à la tâche, qui est en général le thread qui attend la fin de la tâche, ou le thread qui accède à la propriété Result.That exception is propagated back to the thread that joins with the task, which is typically the thread that is waiting for the task to finish or the thread that accesses the Result property. Ce comportement permet d'appliquer la stratégie .NET Framework selon laquelle toutes les exceptions non gérées doivent par défaut détruire le processus.This behavior serves to enforce the .NET Framework policy that all unhandled exceptions by default should terminate the process. Le code appelant peut gérer les exceptions en utilisant l’un des éléments suivants dans un bloc try/catch :The calling code can handle the exceptions by using any of the following in a try/catch block:

Le thread joint peut également gérer des exceptions en accédant à la propriété Exception avant que la tâche ne soit récupérée par le garbage collector.The joining thread can also handle exceptions by accessing the Exception property before the task is garbage-collected. En accédant à cette propriété, vous empêchez l'exception non gérée de déclencher le comportement de propagation de l'exception qui termine le processus lorsque l'objet est finalisé.By accessing this property, you prevent the unhandled exception from triggering the exception propagation behavior that terminates the process when the object is finalized.

Pour plus d’informations sur les exceptions et les tâches, consultez Gestion des exceptions.For more information about exceptions and tasks, see Exception Handling.

Annulation des tâchesCanceling tasks

La classe Task prend en charge l'annulation coopérative et s'intègre pleinement aux classes System.Threading.CancellationTokenSource et System.Threading.CancellationToken, qui ont été introduites dans .NET Framework 4.The Task class supports cooperative cancellation and is fully integrated with the System.Threading.CancellationTokenSource and System.Threading.CancellationToken classes, which were introduced in the .NET Framework 4. De nombreux constructeurs de la classe System.Threading.Tasks.Task prennent un objet CancellationToken en tant que paramètre d'entrée.Many of the constructors in the System.Threading.Tasks.Task class take a CancellationToken object as an input parameter. La plupart des surcharges StartNew et Run incluent également un paramètre CancellationToken.Many of the StartNew and Run overloads also include a CancellationToken parameter.

Vous pouvez créer le jeton et la requête d'annulation ultérieurement, à l'aide de la classe CancellationTokenSource.You can create the token, and issue the cancellation request at some later time, by using the CancellationTokenSource class. Passez le jeton au Task en tant qu'argument et référencez ce même jeton dans votre délégué d'utilisateur, qui répond à une requête d'annulation.Pass the token to the Task as an argument, and also reference the same token in your user delegate, which does the work of responding to a cancellation request.

Pour plus d’informations, consultez Annulation de tâches et Comment : annuler une tâche et ses enfants.For more information, see Task Cancellation and How to: Cancel a Task and Its Children.

Classe TaskFactoryThe TaskFactory class

La classe TaskFactory fournit des méthodes statiques qui encapsulent des modèles communs pour la création et le lancement des tâches et des tâches de continuation.The TaskFactory class provides static methods that encapsulate some common patterns for creating and starting tasks and continuation tasks.

TaskFactory par défaut est accessible en tant que propriété statique dans la classe Task ou Task<TResult>.The default TaskFactory can be accessed as a static property on the Task class or Task<TResult> class. Vous pouvez également instancier directement un TaskFactory et spécifier différentes options qui incluent une option CancellationToken, TaskCreationOptions, TaskContinuationOptions ou TaskScheduler.You can also instantiate a TaskFactory directly and specify various options that include a CancellationToken, a TaskCreationOptions option, a TaskContinuationOptions option, or a TaskScheduler. Toutes les options spécifiées lors de la création de la fabrique de tâches seront appliquées à toutes les tâches qu'elle crée, à moins que la tâche Task ne soit créée à l'aide de l'énumération TaskCreationOptions, auquel cas les options de la tâche remplacent celles de la fabrique de tâches.Whatever options are specified when you create the task factory will be applied to all tasks that it creates, unless the Task is created by using the TaskCreationOptions enumeration, in which case the task's options override those of the task factory.

Tâches sans déléguésTasks without delegates

Dans certains cas, vous pouvez utiliser un Task pour encapsuler une opération asynchrone exécutée par un composant externe au lieu de votre propre délégué utilisateur.In some cases, you may want to use a Task to encapsulate some asynchronous operation that is performed by an external component instead of your own user delegate. Si l'opération est basée sur le modèle de programmation asynchrone Begin/End, vous pouvez utiliser les méthodes FromAsync.If the operation is based on the Asynchronous Programming Model Begin/End pattern, you can use the FromAsync methods. Si ce n'est pas le cas, vous pouvez utiliser l'objet TaskCompletionSource<TResult> pour encapsuler l'opération dans une tâche et, de cette façon, bénéficier de certains des avantages de programmabilité Task, comme par exemple, la prise en charge de la propagation et des continuations d'exceptions.If that is not the case, you can use the TaskCompletionSource<TResult> object to wrap the operation in a task and thereby gain some of the benefits of Task programmability, for example, support for exception propagation and continuations. Pour plus d'informations, consultez TaskCompletionSource<TResult>.For more information, see TaskCompletionSource<TResult>.

Planificateurs personnalisésCustom schedulers

La plupart des développeurs d'applications ou de bibliothèques ne se soucient pas du processeur sur lequel s'exécute la tâche, ni de la manière dont il synchronise son travail avec d'autres tâches ou de la façon dont il est planifié sur le System.Threading.ThreadPool.Most application or library developers do not care which processor the task runs on, how it synchronizes its work with other tasks, or how it is scheduled on the System.Threading.ThreadPool. Ils demandent simplement à ce qu'il s'exécute aussi efficacement que possible sur l'ordinateur hôte.They only require that it execute as efficiently as possible on the host computer. Si vous avez besoin d'un contrôle plus affiné sur les détails de la planification, la bibliothèque parallèle de tâches vous permet de configurer des paramètres dans le planificateur de tâches par défaut et vous permet même de fournir un planificateur personnalisé.If you require more fine-grained control over the scheduling details, the Task Parallel Library lets you configure some settings on the default task scheduler, and even lets you supply a custom scheduler. Pour plus d'informations, consultez TaskScheduler.For more information, see TaskScheduler.

La bibliothèque parallèle de tâches possède plusieurs nouveaux types publics qui sont utiles dans les scénarios parallèles et séquentiels.The TPL has several new public types that are useful in both parallel and sequential scenarios. Ces derniers incluent plusieurs classes de collection thread-safe, rapides et évolutives dans l'espace de noms System.Collections.Concurrent, et plusieurs nouveaux types de synchronisation, tels que System.Threading.Semaphore et System.Threading.ManualResetEventSlim, qui sont plus efficaces que leurs prédécesseurs pour certains genres de charges de travail.These include several thread-safe, fast and scalable collection classes in the System.Collections.Concurrent namespace, and several new synchronization types, for example, System.Threading.Semaphore and System.Threading.ManualResetEventSlim, which are more efficient than their predecessors for specific kinds of workloads. D'autres types nouveaux dans .NET Framework 4, tels que System.Threading.Barrier et System.Threading.SpinLock, fournissent des fonctionnalités qui n'étaient pas disponibles dans les versions précédentes.Other new types in the .NET Framework 4, for example, System.Threading.Barrier and System.Threading.SpinLock, provide functionality that was not available in earlier releases. Pour plus d’informations, consultez Structures de données pour la programmation parallèle.For more information, see Data Structures for Parallel Programming.

Types de tâches personnalisésCustom task types

Nous vous recommandons de ne pas hériter de System.Threading.Tasks.Task ou System.Threading.Tasks.Task<TResult>.We recommend that you do not inherit from System.Threading.Tasks.Task or System.Threading.Tasks.Task<TResult>. Nous vous recommandons d'utiliser plutôt la propriété AsyncState pour associer d'autres données ou états à un objet Task ou Task<TResult>.Instead, we recommend that you use the AsyncState property to associate additional data or state with a Task or Task<TResult> object. Vous pouvez également utiliser des méthodes d'extension pour étendre les fonctionnalités des classes Task et Task<TResult>.You can also use extension methods to extend the functionality of the Task and Task<TResult> classes. Pour plus d’informations sur les méthodes d’extension, consultez Méthodes d’extension et Méthodes d’extension.For more information about extension methods, see Extension Methods and Extension Methods.

Si vous devez hériter de Task ou Task<TResult>, vous ne pouvez pas utiliser les classes Run, Run ou les classes System.Threading.Tasks.TaskFactory, System.Threading.Tasks.TaskFactory<TResult> ou System.Threading.Tasks.TaskCompletionSource<TResult> pour créer des instances de votre tâche personnalisée parce que ces mécanismes créent uniquement des objets Task et Task<TResult>.If you must inherit from Task or Task<TResult>, you cannot use Run, Run, or the System.Threading.Tasks.TaskFactory, System.Threading.Tasks.TaskFactory<TResult>, or System.Threading.Tasks.TaskCompletionSource<TResult> classes to create instances of your custom task type because these mechanisms create only Task and Task<TResult> objects. En outre, vous ne pouvez pas utiliser les mécanismes de continuation des tâches fournis par Task, Task<TResult>TaskFactory et TaskFactory<TResult> pour créer des instances de votre type de tâche personnalisé parce que ces mécanismes créent également uniquement des objets Task et Task<TResult>.In addition, you cannot use the task continuation mechanisms that are provided by Task, Task<TResult>, TaskFactory, and TaskFactory<TResult> to create instances of your custom task type because these mechanisms also create only Task and Task<TResult> objects.

TitreTitle DescriptionDescription
Chaînage des tâches à l’aide de tâches de continuationChaining Tasks by Using Continuation Tasks Décrit le fonctionnement des continuations.Describes how continuations work.
Tâches enfants attachées et détachéesAttached and Detached Child Tasks Décrit la différence entre les tâches enfants attachées et les tâches enfants détachées.Describes the difference between attached and detached child tasks.
Annulation de tâchesTask Cancellation Décrit la prise en charge de l'annulation intégrée dans l'objet Task.Describes the cancellation support that is built into the Task object.
Gestion des exceptionsException Handling Décrit comment les exceptions sur les threads simultanés sont gérées.Describes how exceptions on concurrent threads are handled.
Comment : utiliser parallel_invoke pour exécuter des opérations parallèlesHow to: Use Parallel.Invoke to Execute Parallel Operations Explique comment utiliser Invoke.Describes how to use Invoke.
Comment : retourner une valeur à partir d’une tâcheHow to: Return a Value from a Task Décrit comment retourner des valeurs à partir de tâches.Describes how to return values from tasks.
Comment : annuler une tâche et ses enfantsHow to: Cancel a Task and Its Children Décrit comment annuler des tâches.Describes how to cancel tasks.
Comment : créer des tâches précalculéesHow to: Create Pre-Computed Tasks Décrit comment utiliser la méthode Task.FromResult pour récupérer les résultats d'opérations de téléchargement asynchrones qui sont conservées dans un cache.Describes how to use the Task.FromResult method to retrieve the results of asynchronous download operations that are held in a cache.
Comment : parcourir une arborescence binaire avec des tâches parallèlesHow to: Traverse a Binary Tree with Parallel Tasks Décrit comment utiliser des tâches pour parcourir un arbre binaire.Describes how to use tasks to traverse a binary tree.
Comment : désencapsuler une tâche imbriquéeHow to: Unwrap a Nested Task Montre également comment utiliser la méthode d'extension Unwrap.Demonstrates how to use the Unwrap extension method.
Parallélisme de donnéesData Parallelism Décrit comment utiliser For et ForEach pour créer des boucles parallèles sur des données.Describes how to use For and ForEach to create parallel loops over data.
Programmation parallèleParallel Programming Nœud de niveau supérieur pour la programmation parallèle .NET Framework.Top level node for .NET Framework parallel programming.

Voir aussiSee Also

Programmation parallèleParallel Programming
Exemples de programmation parallèle avec .NET FrameworkSamples for Parallel Programming with the .NET Framework