假设我有一个界面:
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;
}
}
答案 0 :(得分:1)
从您的代码开始,通过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;
});
}