在使用webApi的客户端应用程序中,我有很多方法可以像下面这样异步调用webApi:
var task = Task.Run(async () => await this.SaveObject(User));
return task.Result.Content;
如果保存的对象有问题,异步函数可以引发异常。在这种情况下,我的异常将根据其类型在客户端上处理。问题是异步任务引发异常时,task.Result.Content
会埋在System.AggregateException
内。
现在我这样处理:
try
{
var task = Task.Run(async () => await this.saveObject(User)); return task.Result.Content;
}
catch(AggregateException ex)
{
throw ex.InnerException;
}
我有太多用相同的方法来做的方法。我想知道是否有一种方法可以避免在每个方法中使用try / catch块。也许有一种异常过滤器机制,就像在webApi上使用的那样,可以在一处捕获类中的所有异常?也许我可以用某些属性标记所需的方法?
答案 0 :(得分:2)
首先,我建议您不要在.Result
上使用Task
。请参阅https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html或https://montemagno.com/c-sharp-developers-stop-calling-dot-result/。
如果您遵循上述建议,并在await
块内Task
和try
,它将抛出实际的异常而不是AggregateException
,因此您可以完全避免重新输入代码。
否则,如果您确实想坚持使用.Result
代码,则可以编写一个通用包装方法来为您执行常见的错误处理:
try
{
var task = Task.Run(async () => await this.Object(User));
return task.Result.Content;
}
catch(AggregateException ex)
{
throw ex.InnerException;
}
类似:
return RunAsync(() => this.Object(User));
private T RunAsync<T>(Func<Task<T>> func)
{
try
{
var task = Task.Run(func);
return task.Result;
}
catch(AggregateException ex)
{
throw ex.InnerException;
}
}
编辑: 我刚刚意识到还有另一种方法(请参阅http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html),因为它感觉更隐蔽,但它稍微有点“ hacky”,但这是这样的:
var task = Task.Run(async () => await this.Object(User));
return task.GetAwaiter().GetResult().Content;
.GetAwaiter().GetResult()
将同步等待Task
(根据.Result
),但不会将任何引发的异常包装在AggregateException
中-这似乎是您的期望。