类的异常过滤器有很多不同的方法

时间:2018-08-14 14:28:32

标签: c# multithreading exception exception-handling try-catch

在使用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上使用的那样,可以在一处捕获类中的所有异常?也许我可以用某些属性标记所需的方法?

1 个答案:

答案 0 :(得分:2)

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

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