简体   繁体   English

抛出AggregateException的内部异常

[英]Rethrowing inner exception of an AggregateException

Let's say I have an Interface: 假设我有一个接口:

interface A {
    string Do();
}

and then I implement this interface in a class. 然后我在一个类中实现此接口。 The implementation requires some async operations. 该实现需要一些异步操作。 Something like the following: 类似于以下内容:

class B : A {
    public string Do() {
        return Task1().Result;
    }

    private async Task<string> Task1() {
        var str = await Task2();

        return str + "task1";
    }

    private async Task<string> Task2() {
        using (WebClient client = new WebClient())
        {
            return System.Text.Encoding.UTF8.GetString(await client.DownloadDataTaskAsync(new Uri("http://test.com")));
        }
    }
}

What is the proper way to return, to the external calling code, the first exception that occurs in the async operations chain? 将异步操作链中发生的第一个异常返回给外部调用代码的正确方法是什么? Is the following a good approach? 以下是好的方法吗?

public string Do() {
    try {
        return Task1().Result;
    } catch (AggregateException ex) {
        Exception inner = ex;
        while(inner.InnerException != null) {
            inner = inner.InnerException;
        }

        throw inner;
    }
}

From your code, through the while , I think you want to throw the first exception in AggregateException To do that, you can use Flatten 通过代码,通过while ,我认为您想在AggregateException引发第一个异常。为此,您可以使用Flatten

Flattens an AggregateException instances into a single, new instance. 将AggregateException实例展平为单个新实例。

It helps to put the exceptions in "the same hierarchy", you can then simply call FirstOrDefault to get the first exception. 这有助于将异常置于“相同的层次结构”中,然后可以简单地调用FirstOrDefault来获取第一个异常。

Supposed this code: 假设此代码:

Task.Factory.StartNew(
        async () =>
        {
            await Task.Factory.StartNew(
                () => { throw new Exception("inner"); },
                TaskCreationOptions.AttachedToParent);

            throw new Exception("outer");
        }).Wait();
    }

The stucture of exceptions likes 异常结构喜欢

AggregateException
    Exception: outer
    AggregateException
       Exception: inner

With Flatten , I can get inner 有了Flatten ,我可以获得inner

catch(AggregateException ex)
{
     Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message);
}

but without Flatten , I get AggregateException , which isn't correct 但是没有Flatten ,我得到AggregateException ,这是不正确的

catch(AggregateException ex)
{
     Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message);
}

With your case, this line can help you get the first exception 对于您的情况,此行可以帮助您获得第一个例外

ex.Flatten().InnerExceptions.FirstOrDefault().Message

You have also the method Handle , which help you handle the exception inside AggregateException 您还有方法Handle ,它可以帮助您处理AggregateException内部的异常

catch (AggregateException ex)
{
    ex.Handle(x =>
    {
        if (x is UnauthorizedAccessException)
        {
            //the exception you interested
            throw x;           
        }
        // Other exceptions will not be handled here.
        //some action i.e log
        return false;
    });
}

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

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