Flatten Method
Collapse the table of content
Expand the table of content

AggregateException.Flatten Method ()

 

Flattens an AggregateException instances into a single, new instance.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)

public AggregateException Flatten()

Return Value

Type: System.AggregateException

A new, flattened AggregateException.

If a task has an attached child task that throws an exception, that exception is wrapped in an AggregateException exception before it is propagated to the parent task, which wraps that exception in its own AggregateException exception before it propagates it back to the calling thread. In such cases, the InnerExceptions property of the AggregateException exception that is caught by the Task.Wait, Task<TResult>.Wait, Task.WaitAny or Task.WaitAll method contains one or more AggregateException instances, not the original exceptions that caused the fault. 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 InnerExceptions property of the returned AggregateException object contains the original exceptions.

This method recursively flattens all instances of AggregateException exceptions that are inner exceptions of the current AggregateException instance . The inner exceptions returned in the new AggregateException are the union of all the inner exceptions from exception tree rooted at the current AggregateException instance.

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.

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.

Universal Windows Platform
Available since 4.5
.NET Framework
Available since 4.0
Portable Class Library
Supported in: portable .NET platforms
Silverlight
Available since 5.0
Windows Phone Silverlight
Available since 8.0
Windows Phone
Available since 8.1
Return to top
Show:
© 2016 Microsoft