Gewusst wie: Behandeln von Ausnahmen, die von Aufgaben ausgelöst werden

In den folgenden Beispielen wird gezeigt, wie Sie von einer oder mehreren Aufgaben ausgelöste Ausnahmen behandeln.

Beispiel

In diesem ersten Beispiel wird die System.AggregateException erfasst, und anschließend werden die zugehörigen AggregateExceptionInnerExceptions() analysiert, um festzustellen, ob Ausnahmen mithilfe des Programmcodes behandelt werden können.

' How to: Handle Exceptions Thrown by Tasks
Imports System.Threading.Tasks
Module TaskExceptions

    Function GetAllFiles(ByVal str As String) As String()

        ' Should throw an AccessDenied exception on Vista or later. If you see an "Exception was unhandled
        ' by user code" error, this is because "Just My Code" is enabled. Press F5 to continue execution or 
        ' disable Just My Code.
        Return System.IO.Directory.GetFiles(str, "*.txt", System.IO.SearchOption.AllDirectories)
    End Function

    Sub Main()

        HandleExceptions()
        ' RethrowAllExceptions()
        Console.WriteLine("Press any key.")
        Console.ReadKey()
    End Sub

    Sub HandleExceptions()
        ' Assume this is a user-entered String.
        Dim path = "C:\"

        ' Use this line to throw UnauthorizedAccessException, which we handle.
        Dim task1 = Task(Of String()).Factory.StartNew(Function() GetAllFiles(path))

        ' Use this line to throw an exception that is not handled.
        '  Task task1 = Task.Factory.StartNew(Sub ()   throw new IndexOutOfRangeException()  )
        Try
            task1.Wait()

        Catch ae As AggregateException

            ae.Handle(Function(x)
                          If TypeOf (x) Is UnauthorizedAccessException Then ' This we know how to handle
                              Console.WriteLine("You do not have permission to access all folders in this path.")
                              Console.WriteLine("See your network administrator or try another path.")
                              Return True
                          Else
                              Return False ' Let anything else stop the application.
                          End If
                      End Function)
        End Try

        Console.WriteLine("task1 has completed.")
    End Sub

    Function GetValidExtensions(ByVal path As String) As String()

        If path = "C:\" Then
            Throw New ArgumentException("The system root is not a valid path.")
        End If
        Dim result(10) As String
        Return result
    End Function

    Sub RethrowAllExceptions()

        ' Assume this is a user-entered String.
        Dim path = "C:\"

        Dim myTasks(2) As Task(Of String())
        myTasks(0) = Task(Of String()).Factory.StartNew(Function() GetAllFiles(path))
        myTasks(1) = Task(Of String()).Factory.StartNew(Function() GetValidExtensions(path))
        myTasks(2) = Task(Of String()).Factory.StartNew(Function()
                                                            Dim s(10) As String
                                                            Return s
                                                        End Function)
        Try
            Task.WaitAll(myTasks)
        Catch ae As AggregateException
            Throw ae.Flatten()
        End Try
        Console.WriteLine("task1 has completed.")
    End Sub

End Module

static string[] GetAllFiles(string str)
{
    // Should throw an AccessDenied exception on Vista.
    return System.IO.Directory.GetFiles(str, "*.txt", System.IO.SearchOption.AllDirectories);
}
static void HandleExceptions()
{
    // Assume this is a user-entered string.
    string path = @"C:\";

    // Use this line to throw UnauthorizedAccessException, which we handle.
    Task<string[]> task1 = Task<string[]>.Factory.StartNew(() => GetAllFiles(path));

    // Use this line to throw an exception that is not handled.
    //  Task task1 = Task.Factory.StartNew(() => { throw new IndexOutOfRangeException(); } );
    try
    {
        task1.Wait();
    }
    catch (AggregateException ae)
    {

        ae.Handle((x) =>
        {
            if (x is UnauthorizedAccessException) // This we know how to handle.
            {
                Console.WriteLine("You do not have permission to access all folders in this path.");
                Console.WriteLine("See your network administrator or try another path.");
                return true;
            }
            return false; // Let anything else stop the application.
        });

    }

    Console.WriteLine("task1 has completed.");
}

In diesem Beispiel wird System.AggregateException erfasst, es wird jedoch nicht versucht, eine der inneren Ausnahmen zu behandeln. Stattdessen werden die inneren Ausnahmen mithilfe der Flatten-Methode aus geschachtelten AggregateException-Instanzen extrahiert, und es wird eine einzelne AggregateException erneut ausgelöst, die alle inneren nicht behandelten Ausnahmen enthält. Durch das Abflachen der Ausnahme kann diese vom Clientcode leichter behandelt werden.

Imports System.Threading.Tasks
Module TaskExceptions2

    Sub Main()
        RethrowAllExceptions()
    End Sub
    Function GetAllFiles(ByVal str As String) As String()

        ' Should throw an AccessDenied exception on Vista or later. If you see an "Exception was unhandled
        ' by user code" error, this is because "Just My Code" is enabled. Press F5 to continue execution or 
        ' disable Just My Code.
        Return System.IO.Directory.GetFiles(str, "*.txt", System.IO.SearchOption.AllDirectories)
    End Function


    Function GetValidExtensions(ByVal path As String) As String()

        If path = "C:\" Then
            Throw New ArgumentException("The system root is not a valid path.")
        End If
        Dim result(10) As String
        Return result
    End Function

    Sub RethrowAllExceptions()

        ' Assume this is a user-entered String.
        Dim path = "C:\"

        Dim myTasks(2) As Task(Of String())
        myTasks(0) = Task(Of String()).Factory.StartNew(Function() GetAllFiles(path))
        myTasks(1) = Task(Of String()).Factory.StartNew(Function() GetValidExtensions(path))
        myTasks(2) = Task(Of String()).Factory.StartNew(Function()
                                                            Dim s(10) As String
                                                            Return s
                                                        End Function)
        Try
            Task.WaitAll(myTasks)
        Catch ae As AggregateException
            Throw ae.Flatten()
        End Try
        Console.WriteLine("task1 has completed.")
    End Sub

End Module
static string[] GetValidExtensions(string path)
{
    if (path == @"C:\")
        throw new ArgumentException("The system root is not a valid path.");

    return new string[10];
}
static void RethrowAllExceptions()
{
    // Assume this is a user-entered string.
    string path = @"C:\";


    Task<string[]>[] tasks = new Task<string[]>[3];
    tasks[0] = Task<string[]>.Factory.StartNew(() => GetAllFiles(path));
    tasks[1] = Task<string[]>.Factory.StartNew(() => GetValidExtensions(path));
    tasks[2] = Task<string[]>.Factory.StartNew(() => new string[10]);


    //int index = Task.WaitAny(tasks2);
    //double d = tasks2[index].Result;
    try
    {
        Task.WaitAll(tasks);
    }
    catch (AggregateException ae)
    {
        throw ae.Flatten();
    }

    Console.WriteLine("task1 has completed.");
}

Fügen Sie den Code in das vorherige Beispiel ein, und rufen Sie RethrowAllExceptions in der Main-Methode auf, um dieses Beispiel auszuführen.

Siehe auch

Weitere Ressourcen

Aufgabenparallelität (Task Parallel Library)