重新抛出 AggregateException 的内部异常
Rethrowing inner exception of an AggregateException
假设我有一个接口:
interface A {
string Do();
}
然后我在class中实现了这个接口。该实现需要一些异步操作。类似于以下内容:
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")));
}
}
}
对于外部调用代码,异步操作链中发生的第一个异常,return的正确方法是什么?以下是一个好的方法吗?
public string Do() {
try {
return Task1().Result;
} catch (AggregateException ex) {
Exception inner = ex;
while(inner.InnerException != null) {
inner = inner.InnerException;
}
throw inner;
}
}
根据你的代码,通过 while
,我认为你想在 AggregateException
中抛出第一个异常
为此,您可以使用 Flatten
Flattens an AggregateException instances into a single, new instance.
将异常放在 "the same hierarchy" 中会有所帮助,然后您可以简单地调用 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;
});
}
假设我有一个接口:
interface A {
string Do();
}
然后我在class中实现了这个接口。该实现需要一些异步操作。类似于以下内容:
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")));
}
}
}
对于外部调用代码,异步操作链中发生的第一个异常,return的正确方法是什么?以下是一个好的方法吗?
public string Do() {
try {
return Task1().Result;
} catch (AggregateException ex) {
Exception inner = ex;
while(inner.InnerException != null) {
inner = inner.InnerException;
}
throw inner;
}
}
根据你的代码,通过 while
,我认为你想在 AggregateException
中抛出第一个异常
为此,您可以使用 Flatten
Flattens an AggregateException instances into a single, new instance.
将异常放在 "the same hierarchy" 中会有所帮助,然后您可以简单地调用 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;
});
}