C# 尝试捕获直至成功-泛型方法或委托的执行循环

C# 尝试捕获直至成功-泛型方法或委托的执行循环,c#,generics,methods,delegates,try-catch,C#,Generics,Methods,Delegates,Try Catch,我希望我的代码一直尝试一个方法,直到没有抛出异常为止,但是,与此不同,我希望它被编写为能够运行任何输入委托/方法的通用方法。以下是我的想法,但我不确定如何通过它传递参数或泛型方法: public void tryLoop(Delegate anyMethod, T[] arguments) { while (true) { // Could be replaced by timer timeout

我希望我的代码一直尝试一个方法,直到没有抛出异常为止,但是,与此不同,我希望它被编写为能够运行任何输入委托/方法的通用方法。以下是我的想法,但我不确定如何通过它传递参数或泛型方法:

public void tryLoop(Delegate anyMethod, T[] arguments) {
    while (true) {                              
        // Could be replaced by timer timeout
        try {
            anyMethod(arguments);
            break;
        }
        catch {
            System.Threading.Thread.Sleep(2000); // wait 2 seconds
        }
    }
}
这可能吗


编辑:对于it学者,我也想知道是否也可以返回结果。

一种方法是使用,并删除
参数

public void tryLoop(Action anyMethod) {
    while ( true ) {
        // Could be replaced by timer timeout
        try {
            anyMethod();
            break;
        }
        catch {
            System.Threading.Thread.Sleep(2000); // wait 2 seconds
        }
    }
}
这使您在如何使用它方面获得了最大的自由:

tryLoop(() => string.Reverse("abc"));
或者像这样:

String s1 = "A";
String s2 = "b";

tryLoop(() => string.Concat(s1, s2));
public T tryLoop<T>(Func<T> anyMethod) {
    while ( true ) {
        // Could be replaced by timer timeout
        try {
            return anyMethod();
        }
        catch {
            System.Threading.Thread.Sleep(2000); // wait 2 seconds
        }
    }
}
var reversed = tryLoop(() => string.Reverse("abc"));

String s1 = "A";
String s2 = "b";

var concatenated = tryLoop(() => string.Concat(s1, s2));
正如您在第二个示例中所看到的,您可以直接从被调用的
tryLoop
方法的上下文中获取参数。你可以在那里调用任何东西

这种方法的好处是,您不必像使用
委托那样使用
调用
动态Voke
,而不必使用
操作
,因为这会带来性能损失

如果需要结果,您可以使用替代
操作
重新编写上述内容,如下所示:

String s1 = "A";
String s2 = "b";

tryLoop(() => string.Concat(s1, s2));
public T tryLoop<T>(Func<T> anyMethod) {
    while ( true ) {
        // Could be replaced by timer timeout
        try {
            return anyMethod();
        }
        catch {
            System.Threading.Thread.Sleep(2000); // wait 2 seconds
        }
    }
}
var reversed = tryLoop(() => string.Reverse("abc"));

String s1 = "A";
String s2 = "b";

var concatenated = tryLoop(() => string.Concat(s1, s2));

检查这是否适合你的需要。如果没有,请评论。也不确定它的性能如何

另外,
DynamicInvoke
方法有一个
对象
返回类型。您可以使用它返回委托的结果。您可以将方法的返回类型从
void
更改为
object

public void tryLoop<T>(Delegate anyMethod, T[] arguments)
{
    while (true)
    {                              // Could be replaced by timer timeout
        try
        {
            anyMethod.DynamicInvoke(arguments);
            break;
        }
        catch
        {
            System.Threading.Thread.Sleep(2000); // wait 2 seconds
        }
    }
}
public void tryLoop(委托anyMethod,T[]参数)
{
while(true)
{//可以由计时器超时代替
尝试
{
anyMethod.DynamicInvoke(参数);
打破
}
抓住
{
System.Threading.Thread.Sleep(2000);//等待2秒
}
}
}

希望这对您有所帮助

如果您能满足于使用闭包的要求,那么您就不需要将参数全部传递给这个方法(或者有多个重载)。可以使用
Func
返回结果

  public T tryLoop<T>(Func<T> anyMethod)
  {
     while (true)
     {
        try
        {
           return anyMethod();
        }
        catch
        {
           System.Threading.Thread.Sleep(2000); // *
        }
     }
     return default(T);
  }


  void SomeMethod(int param)
  {
     var someLocal = "Hi";
     var anotherLocal = 0;
     var result = tryLoop(() =>
     {
        Console.WriteLine(someLocal);
        return param + anotherLocal;
     });
     Console.Write(result);
  }
public T tryLoop(Func anyMethod)
{
while(true)
{
尝试
{
返回anyMethod();
}
抓住
{
系统线程线程睡眠(2000);//*
}
}
返回默认值(T);
}
void方法(int参数)
{
var someLocal=“Hi”;
var anotherLocal=0;
var result=tryLoop(()=>
{
Console.WriteLine(本地);
返回参数+另一个本地参数;
});
控制台。写入(结果);
}
老实说,我不会设置无限重试,但是,如果返回了某些类型的
retryable
错误,例如数据库死锁,或者调用不稳定的web服务超时,那么可能需要3到4次重试。异常(如
DivideByZero
FileNotFound
不可能通过无限期运行它们而消失:-)

***特别是对于死锁,建议休眠一段时间,以防其他线程也同时对完全相同的数据进行死锁-您不希望在2000ms内再次发生相同的死锁:-)