Partager via


Comment : attendre la fin d'une ou de plusieurs tâches

Cet exemple indique comment utiliser la méthode Wait ou son équivalent dans la classe Task<TResult>, pour attendre une tâche unique. Il indique également comment utiliser les méthodes statiques WaitAll et WaitAny pour attendre plusieurs tâches.

Exemple

' How to: Wait on One or More Tasks to Complete
Imports System.Threading
Imports System.Threading.Tasks

Module WaitOnTasks

    Dim rand As New Random()
    Sub Main()

        ' Wait on a single task with no timeout specified.
        Dim taskA = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
        taskA.Wait()
        Console.WriteLine("taskA has completed.")


        ' Wait on a single task with a timeout specified.
        Dim taskB = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
        taskB.Wait(100) 'Wait for 100 ms.

        If (taskB.IsCompleted) Then
            Console.WriteLine("taskB has completed.")
        Else
            Console.WriteLine("Timed out before task2 completed.")
        End If

        ' Wait for all tasks to complete.
        Dim myTasks(9) As Task
        For i As Integer = 0 To myTasks.Length - 1
            myTasks(i) = Task.Factory.StartNew(Sub() DoSomeWork(10000000))
        Next
        Task.WaitAll(myTasks)

        ' Wait for first task to complete.
        Dim tasks2(2) As Task(Of Double)

        ' Try three different approaches to the problem. Take the first one.
        tasks2(0) = Task(Of Double).Factory.StartNew(Function() TrySolution1())
        tasks2(1) = Task(Of Double).Factory.StartNew(Function() TrySolution2())
        tasks2(2) = Task(Of Double).Factory.StartNew(Function() TrySolution3())


        Dim index As Integer = Task.WaitAny(tasks2)
        Dim d As Double = tasks2(index).Result
        Console.WriteLine("task(0) completed first with result of {1}.", index, d)
        Console.ReadKey()

    End Sub


    ' Dummy Functions to Simulate Work

    Function DoSomeWork(ByVal val As Integer)
        ' Pretend to do something.
        Thread.SpinWait(val)
    End Function

    Function TrySolution1()

        Dim i As Integer = rand.Next(1000000)
        ' Simulate work by spinning
        Thread.SpinWait(i)
        Return i
    End Function
    Function TrySolution2()

        Dim i As Integer = rand.Next(1000000)
        ' Simulate work by spinning
        Thread.SpinWait(i)
        Return i
    End Function
    Function TrySolution3()

        Dim i As Integer = rand.Next(1000000)
        ' Simulate work by spinning
        Thread.SpinWait(i)
        Thread.SpinWait(1000000)
        Return i
    End Function

End Module

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

    class Program
    {
        static Random rand = new Random();
        static void Main(string[] args)
        {
            // Wait on a single task with no timeout specified.
            Task taskA = Task.Factory.StartNew(() => DoSomeWork(10000000));
            taskA.Wait();
            Console.WriteLine("taskA has completed.");


            // Wait on a single task with a timeout specified.
            Task taskB = Task.Factory.StartNew(() => DoSomeWork(10000000));
            taskB.Wait(100); //Wait for 100 ms.

            if (taskB.IsCompleted)
                Console.WriteLine("taskB has completed.");
            else
                Console.WriteLine("Timed out before taskB completed.");

            // Wait for all tasks to complete.
            Task[] tasks = new Task[10];
            for (int i = 0; i < 10; i++)
            {
                tasks[i] = Task.Factory.StartNew(() => DoSomeWork(10000000));
            }
            Task.WaitAll(tasks);

            // Wait for first task to complete.
            Task<double>[] tasks2 = new Task<double>[3];

            // Try three different approaches to the problem. Take the first one.
            tasks2[0] = Task<double>.Factory.StartNew(() => TrySolution1());
            tasks2[1] = Task<double>.Factory.StartNew(() => TrySolution2());
            tasks2[2] = Task<double>.Factory.StartNew(() => TrySolution3());


            int index = Task.WaitAny(tasks2);
            double d = tasks2[index].Result;
            Console.WriteLine("task[{0}] completed first with result of {1}.", index, d);

            Console.ReadKey();
        }


        static void DoSomeWork(int val)
        {
            // Pretend to do something.
            Thread.SpinWait(val);
        }

        static double TrySolution1()
        {
            int i = rand.Next(1000000);
            // Simulate work by spinning
            Thread.SpinWait(i); 
            return DateTime.Now.Millisecond;
        }
        static double TrySolution2()
        {
            int i = rand.Next(1000000);
            // Simulate work by spinning
            Thread.SpinWait(i); 
            return DateTime.Now.Millisecond;
        }
        static double TrySolution3()
        {
            int i = rand.Next(1000000);
            // Simulate work by spinning
            Thread.SpinWait(i); 
            Thread.SpinWait(1000000);
            return DateTime.Now.Millisecond;
        }


    }

Pour des raisons de simplicité, ces exemples ne montrent pas le code de gestion des exceptions ni le code d'annulation. Dans la plupart des cas, vous devez joindre une méthode Wait à un bloc try-catch car l'attente est le mécanisme par lequel le code du programme gère les exceptions déclenchées par les tâches. Pour plus d'informations, consultez Comment : gérer les exceptions levées par des tâches. Si votre tâche est annulable, vous devez vérifier la propriété IsCanceled ou IsCancellationRequested() avant d'essayer de consommer la tâche ou sa propriété Result(). Pour plus d'informations, consultez Comment : annuler une tâche et ses enfants.

Voir aussi

Concepts

Expressions lambda en PLINQ et dans la bibliothèque parallèle de tâches

Autres ressources

Parallélisme des tâches (bibliothèque parallèle de tâches)