Compartir a través de


Cómo: Esperar a que una o varias tareas se completen

En este ejemplo se muestra cómo utilizar el método Wait o su equivalente en la clase Task<TResult>, para esperar en una tarea única. También se muestra cómo utilizar los métodos WaitAny y WaitAll estáticos para esperar en varias tareas.

Ejemplo

' 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;
        }


    }

Por razones de simplicidad, estos ejemplos no muestran el código de control de excepciones ni el código de cancelación. En la mayoría de los casos, debe incluir un método Wait en un bloque try-catch, porque la espera es el mecanismo por el que el código de programa controla las excepciones que se inician en cualquiera de las tareas. Para obtener más información, vea Cómo: Controlar excepciones iniciadas por tareas. Si la tarea se puede cancelar, debe comprobar las propiedades IsCanceled o IsCancellationRequested() antes de intentar utilizar la tarea o su propiedad Result(). Para obtener más información, vea Cómo: Cancelar una tarea y sus elementos secundarios.

Vea también

Conceptos

Expresiones lambda en PLINQ y TPL

Otros recursos

Paralelismo de tareas (Task Parallel Library)