class 许多不同方法的异常过滤器

Exception filter for the class many different methods

在我使用 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 上使用的机制,可以在一个地方捕获 class 内的所有异常?也许我可以用一些属性来标记需要的方法?

首先,我建议您不要在 Task 上使用 .Result。参见 https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html or https://montemagno.com/c-sharp-developers-stop-calling-dot-result/

如果您遵循上述建议并在 try 块中 await 一个 Task,它将抛出实际异常而不是 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 中 - 这似乎是您的欲望。