AggregateException C#示例

我在网上看到了一个AggregateException的例子,我正在试图弄清楚它是如何工作的,所以我写了一些简单的例子,但由于某种原因我的代码不起作用

有人可以解释一下我的问题是什么

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

你需要在内部exception上调用“Handled”。 从MSDN关于“句柄”的文档:

每次调用谓词都会返回true或false,以指示是否处理了Exception。 在所有调用之后,如果未处理任何exception,则所有未处理的exception将被放入将抛出的新AggregateException中。 否则,Handle方法只返回。 如果对谓词的任何调用抛出exception,它将停止处理任何更多exception并立即按原样传播抛出的exception。

示例代码,也来自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; }); } } 

当使用Parallel时,“job”(这里从0到500000计数)被分成几个工作线程。 其中每一个都可能抛出exception。 在示例中,exception被编码为在10523上运行的线程中发生。在现实世界中,可能发生多个exception(在不同的线程中) – AggregateException只是在Parallel运行时发生的所有exception的“容器”你不会失去任何例外……

AggregateException通常用于捕获exception,这可能在等待Task完成时发生。 因为Task一般可以包含多个其他Task ,我们不知道是否会抛出一个或多个exception。

请检查以下示例:

 // set up your task Action 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); } 

以下是使用AggregateException从exception对象获取内部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; } 

我的解决方法:

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