Ausnahmebehandlung (Task Parallel Library)Exception handling (Task Parallel Library)

Nicht behandelte Ausnahmen, die von innerhalb einer Aufgabe ausgeführtem Benutzercode ausgelöst werden, werden zurück zum aufrufenden Thread geleitet. Hiervon ausgenommen sind bestimmte Szenarios, die weiter unten in diesem Thema beschrieben werden.Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the calling thread, except in certain scenarios that are described later in this topic. Ausnahmen werden weitergegeben, wenn Sie eine der statischen oder instanzbasierten Task.Wait-Methoden verwenden. Zur Behandlung dieser Ausnahmen schließen Sie den Aufruf in eine try/catch-Anweisung ein.Exceptions are propagated when you use one of the static or instance Task.Wait methods, and you handle them by enclosing the call in a try/catch statement. Wenn eine Aufgabe das übergeordnete Element angefügter untergeordneter Aufgaben ist oder wenn Sie auf mehrere Aufgaben warten, können mehrere Ausnahmen ausgelöst werden.If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.

Um alle Ausnahmen zurück an den aufrufenden Thread zu leiten, schließt die Aufgabeninfrastruktur diese in eine AggregateException -Instanz ein.To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance. Die AggregateException -Ausnahme verfügt über eine InnerExceptions -Eigenschaft, die aufgelistet werden kann, um alle ursprünglich ausgelösten Ausnahmen zu analysieren und jede Ausnahme einzeln zu behandeln (bzw. nicht zu behandeln).The AggregateException exception has an InnerExceptions property that can be enumerated to examine all the original exceptions that were thrown, and handle (or not handle) each one individually. Sie können die ursprünglichen Ausnahmen mithilfe der AggregateException.Handle -Methode ebenfalls behandeln.You can also handle the original exceptions by using the AggregateException.Handle method.

Auch wenn nur eine Ausnahme ausgelöst wurde, wird diese in eine AggregateException -Ausnahme eingeschlossen, wie im nachfolgenden Beispiel veranschaulicht.Even if only one exception is thrown, it is still wrapped in an AggregateException exception, as the following example shows.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      try
      {
          task1.Wait();
      }
      catch (AggregateException ae)
      {
          foreach (var e in ae.InnerExceptions) {
              // Handle the custom exception.
              if (e is CustomException) {
                  Console.WriteLine(e.Message);
              }
              // Rethrow any other exception.
              else {
                  throw;
              }
          }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//        This exception is expected!
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Run(Sub() Throw New CustomException("This exception is expected!"))

      Try
         task1.Wait()
      Catch ae As AggregateException
         For Each ex In ae.InnerExceptions
            ' Handle the custom exception.
            If TypeOf ex Is CustomException Then
               Console.WriteLine(ex.Message)
            ' Rethrow any other exception.
            Else
               Throw
            End If
         Next
      End Try
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays the following output:
'       This exception is expected!

Unbehandeltes Ausnahmen vermeiden Sie, indem Sie nur die AggregateException erfassen und die inneren Ausnahmen nicht beachten.You could avoid an unhandled exception by just catching the AggregateException and not observing any of the inner exceptions. Hiervon wird jedoch abgeraten, da dies dem Erfassen des grundlegenden Exception -Typs in nicht parallelen Szenarios entspricht.However, we recommend that you do not do this because it is analogous to catching the base Exception type in non-parallel scenarios. Wenn Sie eine Ausnahme erfassen, ohne Maßnahmen zu deren Behandlung zu ergreifen, weist das Programm ggf. einen unbestimmten Zustand auf.To catch an exception without taking specific actions to recover from it can leave your program in an indeterminate state.

Wenn Sie die Task.Wait-Methode nicht aufrufen möchten, um auf den Abschluss einer Aufgabe zu warten, können Sie auch die AggregateException-Ausnahme der Exception-Eigenschaft der Aufgabe abrufen, wie im folgenden Beispiel dargestellt.If you do not want to call the Task.Wait method to wait for a task's completion, you can also retrieve the AggregateException exception from the task's Exception property, as the following example shows. Weitere Informationen finden Sie im Abschnitt Beachten von Ausnahmen mit der Task.Exception-Eigenschaft dieses Themas.For more information, see the Observing exceptions by using the Task.Exception property section in this topic.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      while(! task1.IsCompleted) {}

      if (task1.Status == TaskStatus.Faulted) {
          foreach (var e in task1.Exception.InnerExceptions) {
              // Handle the custom exception.
              if (e is CustomException) {
                  Console.WriteLine(e.Message);
              }
              // Rethrow any other exception.
              else {
                  throw e;
              }
          }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//        This exception is expected!
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Run(Sub() Throw New CustomException("This exception is expected!"))

      While Not task1.IsCompleted
      End While

      If task1.Status = TaskStatus.Faulted Then
         For Each ex In task1.Exception.InnerExceptions
            ' Handle the custom exception.
            If TypeOf ex Is CustomException Then
               Console.WriteLine(ex.Message)
            ' Rethrow any other exception.
            Else
               Throw ex
            End If
         Next
      End If
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays the following output:
'       This exception is expected!

Wenn Sie nicht auf eine Aufgabe warten, die eine Ausnahme weitergibt, oder auf deren Exception -Eigenschaft zugreifen, wird die Ausnahme entsprechend der .NET-Ausnahmerichtlinie eskaliert, sofern die Aufgabe der Garbage Collection unterliegt.If you do not wait on a task that propagates an exception, or access its Exception property, the exception is escalated according to the .NET exception policy when the task is garbage-collected.

Wenn Ausnahmen mittels Bubbling wieder an den Verbindungsthread übergeben werden können, ist es möglich, dass eine Aufgabe nach dem Auslösen der Ausnahme weiterhin einige Elemente verarbeitet.When exceptions are allowed to bubble up back to the joining thread, it is possible that a task may continue to process some items after the exception is raised.

Hinweis

Wenn "Nur eigenen Code" aktiviert ist, unterbricht Visual Studio die Ausführung in einigen Fällen in der Zeile, die die Ausnahme auslöst, und eine Fehlermeldung zu einer nicht vom Benutzercode behandelten Ausnahme wird angezeigt.When "Just My Code" is enabled, Visual Studio in some cases will break on the line that throws the exception and display an error message that says "exception not handled by user code." Dieser Fehler hat keine Auswirkungen.This error is benign. Sie können F5 drücken, um den Vorgang fortzusetzen. In diesem Fall wird das in den folgenden Beispielen veranschaulichte Ausnahmebehandlungsverhalten angewendet.You can press F5 to continue and see the exception-handling behavior that is demonstrated in these examples. Um zu verhindern, dass Visual Studio die Ausführung beim ersten Fehler unterbricht, deaktivieren Sie das Kontrollkästchen Nur eigenen Code unter Extras, Optionen, Debugging, Allgemein.To prevent Visual Studio from breaking on the first error, just uncheck the Enable Just My Code checkbox under Tools, Options, Debugging, General.

Angefügte untergeordnete Aufgaben und geschachtelte AggregateExceptionsAttached child tasks and nested AggregateExceptions

Wenn eine Aufgabe über eine angefügte untergeordnete Aufgabe verfügt, die eine Ausnahme auslöst, wird diese Ausnahme in AggregateException eingeschlossen, bevor sie an die übergeordnete Aufgabe weitergegeben wird, die diese Ausnahme in eine eigene AggregateException einschließt und sie anschließend an den aufrufenden Thread zurückgibt.If a task has an attached child task that throws an exception, that exception is wrapped in an AggregateException before it is propagated to the parent task, which wraps that exception in its own AggregateException before it propagates it back to the calling thread. In solchen Fällen enthält die InnerExceptions-Eigenschaft der AggregateException-Ausnahme, die bei den Methoden Task.Wait, WaitAny oder WaitAll abgefangen wird, eine oder mehrere AggregateException-Instanzen und nicht die ursprünglichen Ausnahmen, die den Fehler verursacht haben.In such cases, the InnerExceptions property of the AggregateException exception that is caught at the Task.Wait, WaitAny, or WaitAll method contains one or more AggregateException instances, not the original exceptions that caused the fault. Um eine Iteration geschachtelter AggregateException-Ausnahmen zu vermeiden, können Sie mit der Flatten-Methode alle geschachtelten AggregateException-Ausnahmen entfernen, sodass die AggregateException.InnerExceptions-Eigenschaft die ursprünglichen Ausnahmen enthält.To avoid having to iterate over nested AggregateException exceptions, you can use the Flatten method to remove all the nested AggregateException exceptions, so that the AggregateException.InnerExceptions property contains the original exceptions. Im folgenden Beispiel werden geschachtelte AggregateException -Instanzen vereinfacht und in nur einen Schleife behandelt.In the following example, nested AggregateException instances are flattened and handled in just one loop.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Factory.StartNew(() => {
                     var child1 = Task.Factory.StartNew(() => {
                        var child2 = Task.Factory.StartNew(() => {
                            // This exception is nested inside three AggregateExceptions.
                            throw new CustomException("Attached child2 faulted.");
                        }, TaskCreationOptions.AttachedToParent);

                        // This exception is nested inside two AggregateExceptions.
                        throw new CustomException("Attached child1 faulted.");
                     }, TaskCreationOptions.AttachedToParent);
      });

      try {
         task1.Wait();
      }
      catch (AggregateException ae) {
         foreach (var e in ae.Flatten().InnerExceptions) {
            if (e is CustomException) {
               Console.WriteLine(e.Message);
            }
            else {
               throw;
            }
         }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//    Attached child1 faulted.
//    Attached child2 faulted.
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Factory.StartNew(Sub()
                                           Dim child1 = Task.Factory.StartNew(Sub()
                                                                                 Dim child2 = Task.Factory.StartNew(Sub()
                                                                                                                       Throw New CustomException("Attached child2 faulted.")
                                                                                                                    End Sub,
                                                                                                                    TaskCreationOptions.AttachedToParent)
                                                                                                                    Throw New CustomException("Attached child1 faulted.")
                                                                              End Sub,
                                                                              TaskCreationOptions.AttachedToParent)
                                        End Sub)

      Try
         task1.Wait()
      Catch ae As AggregateException
         For Each ex In ae.Flatten().InnerExceptions
            If TypeOf ex Is CustomException Then
               Console.WriteLine(ex.Message)
            Else
               Throw
            End If
         Next
      End Try
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays the following output:
'       Attached child1 faulted.
'       Attached child2 faulted.

Sie können auch die AggregateException.Flatten-Methode verwenden, um die inneren Ausnahmen von mehreren AggregateException-Instanzen erneut auszulösen, die von mehreren Aufgaben in einer einzelnen AggregateException-Instanz ausgelöst wurden, wie im folgenden Beispiel gezeigt.You can also use the AggregateException.Flatten method to rethrow the inner exceptions from multiple AggregateException instances thrown by multiple tasks in a single AggregateException instance, as the following example shows.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
public class Example
{
   public static void Main()
   {
        try {
            ExecuteTasks();
        }
        catch (AggregateException ae) {
            foreach (var e in ae.InnerExceptions) {
                Console.WriteLine("{0}:\n   {1}", e.GetType().Name, e.Message);
            }
        }
   }

   static void ExecuteTasks()
   {
        // Assume this is a user-entered String.
        String path = @"C:\";
        List<Task> tasks = new List<Task>();

        tasks.Add(Task.Run(() => {
                             // This should throw an UnauthorizedAccessException.
                              return Directory.GetFiles(path, "*.txt",
                                                        SearchOption.AllDirectories);
                           }));

        tasks.Add(Task.Run(() => {
                              if (path == @"C:\")
                                 throw new ArgumentException("The system root is not a valid path.");
                              return new String[] { ".txt", ".dll", ".exe", ".bin", ".dat" };
                           }));

        tasks.Add(Task.Run(() => {
                               throw new NotImplementedException("This operation has not been implemented.");
                           }));

        try {
            Task.WaitAll(tasks.ToArray());
        }
        catch (AggregateException ae) {
            throw ae.Flatten();
        }
    }
}
// The example displays the following output:
//       UnauthorizedAccessException:
//          Access to the path 'C:\Documents and Settings' is denied.
//       ArgumentException:
//          The system root is not a valid path.
//       NotImplementedException:
//          This operation has not been implemented.
Imports System.Collections.Generic
Imports System.IO
Imports System.Threading.Tasks

Module Example
    Public Sub Main()
       Try
          ExecuteTasks()
       Catch ae As AggregateException
          For Each e In ae.InnerExceptions
             Console.WriteLine("{0}:{2}   {1}", e.GetType().Name, e.Message,
                               vbCrLf)
          Next
       End Try
    End Sub

    Sub ExecuteTasks()
        ' Assume this is a user-entered String.
        Dim path = "C:\"
        Dim tasks As New List(Of Task)
        
        tasks.Add(Task.Run(Function()
                             ' This should throw an UnauthorizedAccessException.
                              Return Directory.GetFiles(path, "*.txt",
                                                        SearchOption.AllDirectories)
                           End Function))

        tasks.Add(Task.Run(Function()
                              If path = "C:\" Then
                                 Throw New ArgumentException("The system root is not a valid path.")
                              End If
                              Return { ".txt", ".dll", ".exe", ".bin", ".dat" }
                           End Function))

        tasks.Add(Task.Run(Sub()
                              Throw New NotImplementedException("This operation has not been implemented.")
                           End Sub))

        Try
            Task.WaitAll(tasks.ToArray)
        Catch ae As AggregateException
            Throw ae.Flatten()
        End Try
    End Sub
End Module
' The example displays the following output:
'       UnauthorizedAccessException:
'          Access to the path 'C:\Documents and Settings' is denied.
'       ArgumentException:
'          The system root is not a valid path.
'       NotImplementedException:
'          This operation has not been implemented.

Ausnahmen bei getrennten untergeordneten AufgabenExceptions from detached child tasks

Standardmäßig werden untergeordnete Aufgaben als getrennte Aufgaben erstellt.By default, child tasks are created as detached. Von getrennten Aufgaben ausgelöste Ausnahmen müssen in der unmittelbar übergeordneten Aufgabe behandelt oder erneut ausgelöst werden. Sie werden nicht auf die gleiche Weise wie angefügte untergeordnete Aufgaben an den aufrufenden Thread zurück geleitet.Exceptions thrown from detached tasks must be handled or rethrown in the immediate parent task; they are not propagated back to the calling thread in the same way as attached child tasks propagated back. Das übergeordnete Element der höchsten Ebene kann eine Ausnahme von einem getrennten untergeordneten Element manuell erneut auslösen, sodass diese in eine AggregateException eingeschlossen und an den aufrufenden Thread zurück geleitet wird.The topmost parent can manually rethrow an exception from a detached child to cause it to be wrapped in an AggregateException and propagated back to the calling thread.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run(() => {
                       var nested1 = Task.Run(() => {
                                          throw new CustomException("Detached child task faulted.");
                                     });

          // Here the exception will be escalated back to the calling thread.
          // We could use try/catch here to prevent that.
          nested1.Wait();
      });

      try {
         task1.Wait();
      }
      catch (AggregateException ae) {
         foreach (var e in ae.Flatten().InnerExceptions) {
            if (e is CustomException) {
               Console.WriteLine(e.Message);
            }
         }
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//    Detached child task faulted.
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Run(Sub()
                              Dim nestedTask1 = Task.Run(Sub()
                                                            Throw New CustomException("Detached child task faulted.")
                                                         End Sub)
                              ' Here the exception will be escalated back to joining thread.
                              ' We could use try/catch here to prevent that.
                              nestedTask1.Wait()
                           End Sub)

      Try
          task1.Wait()
      Catch ae As AggregateException
          For Each ex In ae.Flatten().InnerExceptions
              If TypeOf ex Is CustomException Then
                  ' Recover from the exception. Here we just
                  ' print the message for demonstration purposes.
                  Console.WriteLine(ex.Message)
              End If
          Next
      End Try
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays the following output:
'       Detached child task faulted.

Selbst wenn Sie mithilfe einer Fortsetzung eine Ausnahme in einer untergeordneten Aufgabe beachten, muss die Ausnahme dennoch von der übergeordneten Aufgabe beachtet werden.Even if you use a continuation to observe an exception in a child task, the exception still must be observed by the parent task.

Ausnahmen mit kooperativem AbbruchExceptions that indicate cooperative cancellation

Wenn Benutzercode in einer Aufgabe auf eine Abbruchanforderung reagiert, besteht das korrekte Verfahren darin, dass eine OperationCanceledException ausgelöst wird, die in dem Abbruchtoken, in dem die Anforderung übermittelt wurde, übergeben wird.When user code in a task responds to a cancellation request, the correct procedure is to throw an OperationCanceledException passing in the cancellation token on which the request was communicated. Bevor die Ausnahme weitergeleitet wird, vergleicht die Aufgabeninstanz das Token in der Ausnahme mit dem Token, das beim Erstellen an sie übergeben wurde.Before it attempts to propagate the exception, the task instance compares the token in the exception to the one that was passed to it when it was created. Stimmen beide Token überein, gibt die Aufgabe eine TaskCanceledException weiter, die in die AggregateExceptioneingeschlossen ist. Diese ist zu sehen, wenn die inneren Ausnahmen analysiert werden.If they are the same, the task propagates a TaskCanceledException wrapped in the AggregateException, and it can be seen when the inner exceptions are examined. Wenn der aufrufende Thread jedoch nicht auf die Aufgabe wartet, wird diese Ausnahme nicht weitergegeben.However, if the calling thread is not waiting on the task, this specific exception will not be propagated. Weitere Informationen finden Sie unter Aufgabenabbruch.For more information, see Task Cancellation.

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var task1 = Task.Factory.StartNew(() =>
{
    CancellationToken ct = token;
    while (someCondition)
    {
        // Do some work...
        Thread.SpinWait(50000);
        ct.ThrowIfCancellationRequested();
    }
},
token);

// No waiting required.
tokenSource.Dispose();
Dim someCondition As Boolean = True
Dim tokenSource = New CancellationTokenSource()
Dim token = tokenSource.Token

Dim task1 = Task.Factory.StartNew(Sub()
                                      Dim ct As CancellationToken = token
                                      While someCondition = True
                                          ' Do some work...
                                          Thread.SpinWait(500000)
                                          ct.ThrowIfCancellationRequested()
                                      End While
                                  End Sub,
                                  token)

Filtern von inneren Ausnahmen mithilfe der Handle-MethodeUsing the handle method to filter inner exceptions

Mit der AggregateException.Handle -Methode können Sie Ausnahmen filtern, die ohne weitere Logik als "behandelt" definiert werden können.You can use the AggregateException.Handle method to filter out exceptions that you can treat as "handled" without using any further logic. Im Benutzerdelegaten, der an die AggregateException.Handle(Func<Exception,Boolean>) -Methode weitergegeben wird, können Sie den Ausnahmetyp, seine Message -Eigenschaft oder beliebige andere Informationen analysieren und ermitteln, ob die Ausnahme keine Auswirkungen zeigt.In the user delegate that is supplied to the AggregateException.Handle(Func<Exception,Boolean>) method, you can examine the exception type, its Message property, or any other information about it that will let you determine whether it is benign. Alle Ausnahmen, für die der Delegat false zurückgibt, werden in einer neuen AggregateException-Instanz erneut ausgelöst, sobald die AggregateException.Handle-Methode zurückkehrt.Any exceptions for which the delegate returns false are rethrown in a new AggregateException instance immediately after the AggregateException.Handle method returns.

Das folgende Beispiel ist zum ersten Beispiel dieses Themas funktional äquivalent, das jede Ausnahme in der AggregateException.InnerExceptions-Auflistung untersucht.The following example is functionally equivalent to the first example in this topic, which examines each exception in the AggregateException.InnerExceptions collection. Dieser Ausnahmehandler ruft stattdessen das AggregateException.Handle-Methodenobjekt für jede Ausnahme auf und löst nur die Ausnahmen erneut aus, die keine CustomException-Instanzen sind.Instead, this exception handler calls the AggregateException.Handle method object for each exception, and only rethrows exceptions that are not CustomException instances.

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );

      try {
          task1.Wait();
      }
      catch (AggregateException ae)
      {
         // Call the Handle method to handle the custom exception,
         // otherwise rethrow the exception.
         ae.Handle(ex => { if (ex is CustomException)
                             Console.WriteLine(ex.Message);
                          return ex is CustomException;
                        });
      }
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays the following output:
//        This exception is expected!
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Run(Sub() Throw New CustomException("This exception is expected!"))

      Try
         task1.Wait()
      Catch ae As AggregateException
         ' Call the Handle method to handle the custom exception,
         ' otherwise rethrow the exception.
         ae.Handle(Function(e)
                      If TypeOf e Is CustomException Then
                         Console.WriteLine(e.Message)
                      End If
                      Return TypeOf e Is CustomException
                   End Function)
      End Try
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays the following output:
'       This exception is expected!

Nachfolgend finden Sie ein vollständigeres Beispiel, das die AggregateException.Handle-Methode verwendet, um beim Auflisten von Dateien für eine UnauthorizedAccessException-Ausnahme eine besondere Behandlung zu bieten.The following is a more complete example that uses the AggregateException.Handle method to provide special handling for an UnauthorizedAccessException exception when enumerating files.

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

public class Example
{
    public static void Main()
    {
        // This should throw an UnauthorizedAccessException.
       try {
           var files = GetAllFiles(@"C:\");
           if (files != null)
              foreach (var file in files)
                 Console.WriteLine(file);
        }
        catch (AggregateException ae) {
           foreach (var ex in ae.InnerExceptions)
               Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
        }
        Console.WriteLine();

        // This should throw an ArgumentException.
        try {
           foreach (var s in GetAllFiles(""))
              Console.WriteLine(s);
        }
        catch (AggregateException ae) {
           foreach (var ex in ae.InnerExceptions)
               Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
        }
    }

    static string[] GetAllFiles(string path)
    {
       var task1 = Task.Run( () => Directory.GetFiles(path, "*.txt",
                                                      SearchOption.AllDirectories));

       try {
          return task1.Result;
       }
       catch (AggregateException ae) {
          ae.Handle( x => { // Handle an UnauthorizedAccessException
                            if (x is UnauthorizedAccessException) {
                                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 x is UnauthorizedAccessException;
                          });
          return Array.Empty<String>();
       }
   }
}
// The example displays the following output:
//       You do not have permission to access all folders in this path.
//       See your network administrator or try another path.
//
//       ArgumentException: The path is not of a legal form.
Imports System.IO
Imports System.Threading.Tasks

Module Example
    Public Sub Main()
        ' This should throw an UnauthorizedAccessException.
       Try
           Dim files = GetAllFiles("C:\")
           If files IsNot Nothing Then
              For Each file In files
                 Console.WriteLine(file)
              Next
           End If
        Catch ae As AggregateException
           For Each ex In ae.InnerExceptions
               Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message)
           Next
        End Try
        Console.WriteLine()

       ' This should throw an ArgumentException.
        Try
           For Each s In GetAllFiles("")
              Console.WriteLine(s)
           Next
        Catch ae As AggregateException
           For Each ex In ae.InnerExceptions
               Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message)
           Next
        End Try
        Console.WriteLine()
    End Sub

    Function GetAllFiles(ByVal path As String) As String()
       Dim task1 = Task.Run( Function()
                                Return Directory.GetFiles(path, "*.txt",
                                                          SearchOption.AllDirectories)
                             End Function)
       Try
          Return task1.Result
       Catch ae As AggregateException
          ae.Handle( Function(x)
                        ' Handle an UnauthorizedAccessException
                        If TypeOf x Is UnauthorizedAccessException Then
                            Console.WriteLine("You do not have permission to access all folders in this path.")
                            Console.WriteLine("See your network administrator or try another path.")
                        End If
                        Return TypeOf x Is UnauthorizedAccessException
                     End Function)
       End Try
       Return Array.Empty(Of String)()
    End Function
End Module
' The example displays the following output:
'       You do not have permission to access all folders in this path.
'       See your network administrator or try another path.
'
'       ArgumentException: The path is not of a legal form.

Berücksichtigen von Ausnahmen mit der Task.Exception-EigenschaftObserving exceptions by using the Task.Exception property

Wenn eine Aufgabe mit einem TaskStatus.Faulted -Zustand abgeschlossen wird, kann die zugehörige Exception -Eigenschaft analysiert werden, um die spezifische Ausnahme zu ermitteln, die den Fehler verursacht hat.If a task completes in the TaskStatus.Faulted state, its Exception property can be examined to discover which specific exception caused the fault. Eine gute Möglichkeit, die Exception -Eigenschaft zu beachten, ist eine Fortsetzung, die nur bei einem Fehler in der vorausgehenden Aufgabe ausgeführt wird, wie im folgenden Beispiel gezeigt.A good way to observe the Exception property is to use a continuation that runs only if the antecedent task faults, as shown in the following example.

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

public class Example
{
   public static void Main()
   {
      var task1 = Task.Run(() =>
                           { throw new CustomException("task1 faulted.");
      }).ContinueWith( t => { Console.WriteLine("{0}: {1}",
                                                t.Exception.InnerException.GetType().Name,
                                                t.Exception.InnerException.Message);
                            }, TaskContinuationOptions.OnlyOnFaulted);
      Thread.Sleep(500);
   }
}

public class CustomException : Exception
{
   public CustomException(String message) : base(message)
   {}
}
// The example displays output like the following:
//        CustomException: task1 faulted.
Imports System.Threading
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim task1 = Task.Factory.StartNew(Sub()
                                           Throw New CustomException("task1 faulted.")
                                        End Sub).
                  ContinueWith(Sub(t)
                                  Console.WriteLine("{0}: {1}",
                                                    t.Exception.InnerException.GetType().Name,
                                                    t.Exception.InnerException.Message)
                               End Sub, TaskContinuationOptions.OnlyOnFaulted)

      Thread.Sleep(500)
   End Sub
End Module

Class CustomException : Inherits Exception
   Public Sub New(s As String)
      MyBase.New(s)
   End Sub
End Class
' The example displays output like the following:
'       CustomException: task1 faulted.

In einer realen Anwendung würde der Fortsetzungsdelegat ausführliche Informationen zu der Ausnahme protokollieren und möglicherweise neue Aufgaben erzeugen, um die Ausnahme zu beheben.In a real application, the continuation delegate could log detailed information about the exception and possibly spawn new tasks to recover from the exception.

UnobservedTaskException-EreignisUnobservedTaskException event

In einigen Szenarien können häufig Ausnahmen ohne Auswirkungen auftreten (z. B. wenn Sie nicht vertrauenswürdige Plug-Ins hosten), und es kann schwierig sein, alle Ausnahmen manuell zu überwachen.In some scenarios, such as when hosting untrusted plug-ins, benign exceptions might be common, and it might be too difficult to manually observe them all. In diesen Fällen können Sie das TaskScheduler.UnobservedTaskException -Ereignis behandeln.In these cases, you can handle the TaskScheduler.UnobservedTaskException event. Mit der an den Handler übergebenen System.Threading.Tasks.UnobservedTaskExceptionEventArgs -Instanz kann verhindert werden, dass die nicht überwachte Ausnahme wieder an den Verbindungsthread übergeben wird.The System.Threading.Tasks.UnobservedTaskExceptionEventArgs instance that is passed to your handler can be used to prevent the unobserved exception from being propagated back to the joining thread.

Siehe auchSee also