C# 方法调用其他方法并处理异常 背景:

C# 方法调用其他方法并处理异常 背景:,c#,.net,delegates,try-catch,.net-4.5,C#,.net,Delegates,Try Catch,.net 4.5,我编写了一个C#应用程序,它从web服务调用多个方法。方法是从Main中的循环、某些类等调用的。由于相同的原因,这些方法中的每一种都可能失败: 连接超时 Web服务内部错误 会话到期 如果这些方法中的任何一个失败,我只需要等待几秒钟(或者调用一个登录方法),然后再次调用它们 问题: 我不想为所有这些方法的每次调用编写本质上相同的try/catch块,因此我需要另一个通用方法,它能够调用所有其他方法,而不考虑其名称和参数,然后捕获一些常见的异常,必要时再次调用该方法,并返回值 方法授权听起来很

我编写了一个C#应用程序,它从web服务调用多个方法。方法是从Main中的循环、某些类等调用的。由于相同的原因,这些方法中的每一种都可能失败:

  • 连接超时
  • Web服务内部错误
  • 会话到期
如果这些方法中的任何一个失败,我只需要等待几秒钟(或者调用一个登录方法),然后再次调用它们

问题: 我不想为所有这些方法的每次调用编写本质上相同的try/catch块,因此我需要另一个通用方法,它能够调用所有其他方法,而不考虑其名称和参数,然后捕获一些常见的异常,必要时再次调用该方法,并返回值


方法授权听起来很简单,但我真的不知道如何解决这个问题。任何帮助都将不胜感激。

听起来你可能想要这样的东西:

private T CallWithRetries<T>(Func<T> call)
{
    // TODO: Work out number of retries, etc.
    for (int i = 0; i < 3; i++)
    {
        try
        {
            return call();
        }
        catch (FooException e)
        {
            // Determine whether or not to retry, log etc. If this is the
            // last iteration, just rethrow - or keep track of all the exceptions
            // so far and throw an AggregateException containing them.
        }
    }
    throw new InvalidOperationException("Shouldn't get here...");
}

对于任何不返回值的调用,您都可以使用类似的方法和
操作
参数。

听起来您可能需要这样的方法:

private T CallWithRetries<T>(Func<T> call)
{
    // TODO: Work out number of retries, etc.
    for (int i = 0; i < 3; i++)
    {
        try
        {
            return call();
        }
        catch (FooException e)
        {
            // Determine whether or not to retry, log etc. If this is the
            // last iteration, just rethrow - or keep track of all the exceptions
            // so far and throw an AggregateException containing them.
        }
    }
    throw new InvalidOperationException("Shouldn't get here...");
}

对于任何不返回值的调用,您可以使用带有
操作
参数的类似方法。

您可以创建如下方法:

private void CallWebMethod(Action methodToBeCalled)
{
    try 
    {           
        methodToBeCalled();
    }
    catch (Exception ex)
    {

        //Log exception
    }              
}
使用以下命令调用不带任何参数的方法:

CallWebMethod(someMethod);
CallWebMethod(() => someMethodWithArgument(args));
使用以下参数调用具有参数的方法:

CallWebMethod(someMethod);
CallWebMethod(() => someMethodWithArgument(args));

您可以创建如下方法:

private void CallWebMethod(Action methodToBeCalled)
{
    try 
    {           
        methodToBeCalled();
    }
    catch (Exception ex)
    {

        //Log exception
    }              
}
使用以下命令调用不带任何参数的方法:

CallWebMethod(someMethod);
CallWebMethod(() => someMethodWithArgument(args));
使用以下参数调用具有参数的方法:

CallWebMethod(someMethod);
CallWebMethod(() => someMethodWithArgument(args));


将循环包装在Try/Catch中,并将句柄错误逻辑放入Catch语句中,然后继续。它是什么类型的web服务?Soap/Restful/WCF如果是Soap或WCF,我假设您正在使用内置的visualstudio add引用来构建代理类?如果您使用的是restful网络客户端?@Anon这正是我想要避免的。我希望这些方法中的每一种都有通用的错误处理方法,我将来也会用到这些方法。@RickyJones它是SOAP,是的,我使用的是VS 2012 Web引用(不是服务引用)。在Try/Catch中包装循环,并将句柄错误逻辑放在Catch语句中,然后继续。它是什么类型的web服务?Soap/Restful/WCF如果是Soap或WCF,我假设您正在使用内置的visualstudio add引用来构建代理类?如果您使用的是restful网络客户端?@Anon这正是我想要避免的。我希望这些方法中的每一种都有通用的错误处理方法,我将来也会用到这些方法。@RickyJones它是SOAP,是的,我使用的是VS 2012 Web引用(不是服务引用)。我喜欢这个答案,你可以更进一步。代理类是部分类,您可以对它们进行扩展,以进行更强类型的调用,然后在引擎盖下使用重试方法。谢谢,就是这样!但是还有一件事我没有提到:这些方法也有一些
out
参数。它们会得到适当的处理吗?@frikozoid:这取决于你所说的“适当”是什么意思——但只要你给用于
out
参数的变量赋予初始值,它就应该有效。这与普通的方法调用不同,因为编译器在方法正常返回之前不“知道”委托将被成功调用。企业库在瞬态故障处理块中有一些好东西,可以使用规范之类的模式来封装故障并重试逻辑策略以反转依赖关系。我喜欢这个答案,你可以更进一步。代理类是部分类,您可以对它们进行扩展,以进行更强类型的调用,然后在引擎盖下使用重试方法。谢谢,就是这样!但是还有一件事我没有提到:这些方法也有一些
out
参数。它们会得到适当的处理吗?@frikozoid:这取决于你所说的“适当”是什么意思——但只要你给用于
out
参数的变量赋予初始值,它就应该有效。这与普通的方法调用不同,因为编译器在方法正常返回之前不“知道”委托将被成功调用。企业库在瞬态故障处理块中有一些好东西,可以使用规范之类的模式来封装故障并重试逻辑策略以反转依赖关系。谢谢但是如果传递一个带参数的方法,使用
Action
不会使它中断吗?我想应该改为
Func
。实际上,您不能用参数传递方法,但如果用返回类型传递方法,则会使其中断。谢谢。但是如果传递一个带参数的方法,使用
Action
不会使它中断吗?我想应该改为
Func
。实际上,您不能用参数传递方法,但如果用返回类型传递方法,则会使其中断。