web-dev-qa-db-fra.com

Exemple d'aggregateException C #

J'ai vu un exemple d'exception AggregateException sur le Web et j'essaie de comprendre comment cela fonctionne. J'ai donc écrit un exemple simple, mais mon code ne fonctionne pas

Quelqu'un pourrait-il m'expliquer quel est le problème

    public static void Main()
    {
        try
        {
            Parallel.For(0, 500000, i =>
            {
                if (i == 10523)
                    throw new TimeoutException("i = 10523");

                Console.WriteLine(i + "\n");
            });
        }
        catch (AggregateException exception)
        {
            foreach (Exception ex in exception.InnerExceptions)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
20
Dan

Vous devez appeler "manipulé" sur les exceptions internes. De la documentation de MSDN sur "Handle":

Chaque appel du prédicat renvoie true ou false pour indiquer si l'exception a été gérée. Après toutes les invocations, si des exceptions ne sont pas gérées, toutes les exceptions non gérées seront placées dans une nouvelle AggregateException qui sera levée. Sinon, la méthode Handle retourne simplement. Si des invocations du prédicat lève une exception, le traitement de toutes les exceptions sera interrompu et propagé immédiatement l'exception levée telle quelle.

L'exemple de code, également de MSDN:

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;
                        });
      }
   }
16
DLCross

Lors de l'utilisation de Parallel, le "travail" (comptant ici de 0 à 500 000) est divisé en plusieurs threads de travail . Chacun de ceux-ci peut générer une exception. Dans l'exemple, l'exception est codée dans le thread travaillant sur 10523 . Dans un scénario réel, plusieurs exceptions pourraient se produire (dans différents threads) - AggregateException est simplement un "conteneur" pour toutes les exceptions se produisant pendant que Parallel est en cours d'exécution afin de ne perdre aucune exception ...

12
Yahia

AggregateException est souvent utilisé pour intercepter des exceptions pouvant survenir lors de l'attente d'une Task. Étant donné que Task peut en général être composé de plusieurs autres, nous ne savons pas si une ou plusieurs exceptions seront levées.

Vérifiez l'exemple suivant:

// set up your task
Action<int> job = (int i) =>
{
    if (i % 100 == 0)
        throw new TimeoutException("i = " + i);
};

// we want many tasks to run in paralell
var tasks = new Task[1000];
for (var i = 0; i < 1000; i++)
{
    // assign to other variable,
    // or it will use the same number for every task
    var j = i; 
    // run your task
    var task = Task.Run(() => job(j));
    // save it
    tasks[i] = task;
}

try
{
    // wait for all the tasks to finish in a blocking manner
    Task.WaitAll(tasks);

}
catch (AggregateException e)
{
    // catch whatever was thrown
    foreach (Exception ex in e.InnerExceptions)
        Console.WriteLine(ex.Message);
}
9
Kędrzu

Voici une utilisation pratique de AggregateException pour obtenir l’exception interne d’un objet exception,

    private static Exception GetFirstRealException(Exception exception)
    {
        Exception realException = exception;
        var aggregateException = realException as AggregateException;

        if (aggregateException != null)
        {
            realException = aggregateException.Flatten().InnerException; // take first real exception

            while (realException != null && realException.InnerException != null)
            {
                realException = realException.InnerException;
            }
        }

        return realException ?? exception;
    }
1
Dhanuka777

Ma façon de le résoudre:

var tasks = new Task[] { DoSomethingAsync(), DoSomethingElseAsync() };

try
{
    await Task.WhenAll(tasks).ConfigureAwait(false);
}
catch (AggregateException ex)
{
    var flatAgrExs = ex.Flatten().InnerExceptions;

    foreach(var agrEx in flatAgrExs)
    {
        //handle out errors
        logger.LogError(agrEx, "Critical Error occurred");
    }
}