简体   繁体   English

AggregateException C# 示例

[英]AggregateException C# example

I have seen an example of AggregateException on the web and I'm trying to figure out how it works.我在 web 上看到了AggregateException的示例,我正在尝试弄清楚它是如何工作的。 I have written a simple example, but my code for some reason doesn't work.我写了一个简单的例子,但由于某种原因我的代码不起作用。

Could someone explain to me what the problem is?有人可以向我解释问题是什么吗?

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

You need to call Handle on the inner exceptions.您需要在内部异常上调用Handle From MSDN's documentation on Handle :来自MSDN关于Handle的文档:

Each invocation of the predicate returns true or false to indicate whether the Exception was handled.谓词的每次调用都返回 true 或 false 以指示是否处理了异常。 After all invocations, if any exceptions went unhandled, all unhandled exceptions will be put into a new AggregateException which will be thrown.在所有调用之后,如果有任何异常未处理,所有未处理的异常将被放入一个新的 AggregateException 中,该异常将被抛出。 Otherwise, the Handle method simply returns.否则,Handle 方法简单地返回。 If any invocations of the predicate throws an exception, it will halt the processing of any more exceptions and immediately propagate the thrown exception as-is.如果谓词的任何调用引发异常,它将停止处理任何更多异常并立即按原样传播引发的异常。

The example code, also from MSDN:示例代码,同样来自 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;
        });
    }
}

When using Parallel the "job" (here counting from 0 to 500000) gets split onto several worker threads.当使用 Parallel 时,“作业”(这里从 0 到 500000 计数)被拆分到多个工作线程上。 Each of these could throw an exception.其中每一个都可能引发异常。 In the sample the exception is coded to happen in the thread working on 10523. In a real world scenario more than one exception could happen (in different threads) - the AggregateException is just a "container" for all exceptions occuring while Parallel is running so that you don't lose any exception...在示例中,异常被编码为在 10523 上工作的线程中发生。在现实世界中,可能会发生多个异常(在不同的线程中) - AggregateException 只是 Parallel 运行时发生的所有异常的“容器”,所以你不会失去任何例外......

AggregateException is often used for catching exceptions, that might occur when waiting for a Task to complete. AggregateException通常用于捕获可能在等待Task完成时发生的异常。 Because Task in general can consist of multiple others, we do not know, whether there will be one or more exceptions thrown.因为Task通常可以包含多个其他的,我们不知道是否会抛出一个或多个异常。

Check the following example:检查以下示例:

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

Here is a practical use of AggregateException to get the inner exception from an exception object,下面是实际使用 AggregateException 从异常 object 中获取内部异常,

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

My way to resolve it:我的解决方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM