Gewusst wie: Warten bis zum Abschluss einer oder mehrerer Aufgaben

In diesem Beispiel wird gezeigt, wie Sie mithilfe der Wait-Methode oder deren Entsprechung in der Task<TResult>-Klasse auf eine einzelne Aufgabe warten. Darüber hinaus erfahren Sie, wie Sie die statischen Methoden WaitAll und WaitAny verwenden, um auf mehrere Aufgaben zu warten.

Beispiel

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


    }

Zur Vereinfachen wird in diesen Beispielen kein Ausnahmebehandlungscode oder Abbruchcode dargestellt. In den meisten Fällen müssen Sie eine Wait-Methode in einen try/catch-Block einschließen, da das Warten vom Programmcode als Mechanismus verwendet wird, um von den Aufgaben ausgelöste Ausnahmen zu behandeln. Weitere Informationen finden Sie unter Gewusst wie: Behandeln von Ausnahmen, die von Aufgaben ausgelöst werden. Wenn die Aufgabe abgebrochen werden kann, sollten Sie die IsCanceled-Eigenschaft oder IsCancellationRequested()-Eigenschaft überprüfen, bevor Sie die Aufgabe oder deren Result()-Eigenschaft nutzen. Weitere Informationen finden Sie unter Gewusst wie: Abbrechen einer Aufgabe und ihrer untergeordneten Elemente.

Siehe auch

Konzepte

Lambda-Ausdrücke in PLINQ und TPL

Weitere Ressourcen

Aufgabenparallelität (Task Parallel Library)