AggregateException.Flatten Метод

Определение

Выполняет сведение экземпляров AggregateException в один новый экземпляр.

public:
 AggregateException ^ Flatten();
public AggregateException Flatten ();
member this.Flatten : unit -> AggregateException
Public Function Flatten () As AggregateException

Возвращаемое значение

AggregateException

Новый сведенный экземпляр AggregateException.

Примеры

В следующем примере вложенные экземпляры AggregateException сглаживаются и обрабатываются всего в одном цикле.

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.
open System
open System.Threading.Tasks

type CustomException(message) =
    inherit Exception(message)

let task1 =
    Task.Factory.StartNew (fun () ->
        let child1 =
            Task.Factory.StartNew(
                (fun () ->
                    let child2 =
                        Task.Factory.StartNew(
                            (fun () -> raise (CustomException "Attached child2 faulted,")),
                            TaskCreationOptions.AttachedToParent
                        )
                    raise (CustomException "Attached child1 faulted.")),
                TaskCreationOptions.AttachedToParent
            )
        ()
    )

try
    task1.Wait()
with
| :? AggregateException as ae ->
    for e in ae.Flatten().InnerExceptions do
        if e :? CustomException then
            printfn "%s" e.Message
        else
            reraise()
        
// 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.

Вы также можете использовать метод AggregateException.Flatten, чтобы повторно создать в одном экземпляре AggregateException все вложенные исключения, полученные в нескольких экземплярах AggregateException от нескольких задач, как показано в следующем примере.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

public class Example2
{
   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.
open System
open System.IO
open System.Threading.Tasks

let executeTasks () =
    // Assume this is a user-entered String.
    let path = @"C:\"

    let tasks =
        [| Task.Run (fun () ->
               // This should throw an UnauthorizedAccessException.
               Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories))
           :> Task
           Task.Run (fun () ->
               if path = @"C:\" then
                   raise (ArgumentException "The system root is not a valid path.")

               [| ".txt"; ".dll"; ".exe"; ".bin"; ".dat" |])
           :> Task
           Task.Run(fun () -> raise (NotImplementedException "This operation has not been implemented")) |]

    try
        Task.WaitAll(tasks)
    with
    | :? AggregateException as ae -> raise (ae.Flatten())

try
    executeTasks ()
with 
| :? AggregateException as ae ->
    for e in ae.InnerExceptions do
        printfn $"{e.GetType().Name}:\n   {e.Message}"

// 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.

Комментарии

Если задача имеет присоединенную дочернюю задачу, которая создает исключение, это исключение упаковывается в AggregateException исключение перед его распространением в родительскую задачу, которая заключает это исключение в собственное AggregateException исключение перед его распространением обратно в вызывающий поток. В таких случаях свойство исключения, InnerExceptions перехватаемое методом Task.Wait, Task.WaitAll WaitTask.WaitAny содержит один или несколько AggregateException экземпляров, а не исходные исключения, вызвавшие ошибку.AggregateException Чтобы итерировать AggregateException вложенные исключения, можно использовать Flatten метод для удаления всех вложенных AggregateException исключений, чтобы InnerExceptions свойство возвращаемого AggregateException объекта содержало исходные исключения.

Этот метод рекурсивно преобразует все экземпляры исключений AggregateException , которые являются внутренними исключениями текущего AggregateException экземпляра. Внутренние исключения, возвращаемые в новом AggregateException , являются объединением всех внутренних исключений из дерева исключений, корневого в текущем AggregateException экземпляре.

Применяется к

См. также раздел