2

假设我有一个接口:

interface A {
    string Do();
}

然后我在一个类中实现这个接口。该实现需要一些异步操作。类似于以下内容:

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

将异步操作链中发生的第一个异常返回给外部调用代码的正确方法是什么?以下是一个好方法吗?

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

        throw inner;
    }
}
4

1 回答 1

2

从您的代码中,通过while,我认为您想在中抛出第一个异常AggregateException 要做到这一点,您可以使用Flatten

将 AggregateException 实例展平为单个新实例。

它有助于将异常放在“相同的层次结构”中,然后您可以简单地调用FirstOrDefault以获取第一个异常。

假设这段代码:

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

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

异常的结构喜欢

AggregateException
    Exception: outer
    AggregateException
       Exception: inner

Flatten,我可以得到inner

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

但没有Flatten,我得到AggregateException,这是不正确的

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

对于您的情况,此行可以帮助您获得第一个异常

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

您还有方法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;
    });
}
于 2018-08-08T10:15:35.410 回答