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());
}
}
}
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;
});
}
}
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 ...
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);
}
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;
}
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");
}
}