我希望我的代码继续尝试一个方法,直到没有抛出异常,但是,与this question不同,我希望它被编写为能够运行任何输入委托/方法的通用方法。以下是我的想法,但我不确定如何通过它传递参数或泛型方法:
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
}
}
}
这可能吗?
编辑:对于它的学者,我也很想知道是否可以返回结果。
答案 0 :(得分:3)
如果您可以使用闭包,则不需要将参数传递给此方法(或具有多个重载)。可以使用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);
}
说实话,我不会设置无限重试,但是 - 如果返回了某些类型的retryable
错误,例如数据库死锁,或者调用不稳定的Web服务的超时,然后可能有3或4次重试。 DivideByZero
或FileNotFound
这样的例外情况无法通过无限期运行而消失: - )
***特别是对于死锁,建议为random period休眠,以防万一其他线程也同时在完全相同的数据上死锁 - 你不希望在2000ms内发生同样的死锁重复: - 。)
答案 1 :(得分:2)
执行此操作的方法是使用Action
,然后删除arguments
参数:
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));
正如您在第二个示例中所看到的,您可以直接从被调用的tryLoop
方法的上下文中获取参数。你可以在那里调用任何东西。
这种方法的好处在于,您不必像使用Invoke
而不是DynamicInvoke
一样使用Delegate
或Action
,因为这会带来性能损失
如果您需要结果,可以使用Func<T>
代替Action
重写上述内容,如下所示:
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));
答案 2 :(得分:1)
检查这是否符合您的需求。如果没有,那么请评论。也不确定它的性能如何。
DynamicInvoke
方法也有object
返回类型。这可以用来返回委托的结果。您可以将方法的返回类型从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
}
}
}
希望这有帮助