我注意到这个问题在我做的大多数事情中发生了很多,所以我认为必须有一个设计模式。
基本上,如果抛出异常,请尝试解决问题并重试。如果我把它放在try中,它所做的只是捕获异常,但我想重试它正在做的任何事情,如果它再次失败,再次重试一定次数。
这种东西有共同的模式吗?
答案 0 :(得分:17)
检查这个答案..希望有帮助你
Cleanest way to write retry logic?
public static class RetryUtility
{
public static void RetryAction(Action action, int numRetries, int retryTimeout)
{
if(action == null)
throw new ArgumenNullException("action");
do
{
try
{
action();
return;
}
catch
{
if(numRetries <= 0)
throw; // Avoid silent failure
else
{
Thread.Sleep(retryTimeout);
numRetries--;
}
}
}
while(numRetries > 0);
}
}
呼叫
RetryUtility.RetryAction( () => SomeFunctionThatCanFail(), 3, 1000 );
归功于LBushkin
答案 1 :(得分:6)
这是无限运行但是很容易为while子句
添加一个循环计数器 var solved = false;
var tries = 0;
while (!solved)
{
try
{
//Do Something
solved = true;
}
catch
{
//Fix error
}
finally
{
if(solved || IsRediculous(tries))
break;
tries++;
}
}
答案 2 :(得分:2)
在循环中尝试/捕获,带有重试计数器?
编辑:你需要“重试其正在做的事情”,你需要自定义逻辑,如何重试变化很大(即重新打开流,重新创建对象,暂停X毫秒等等) ,所以你需要在每个原子操作的循环中使用它自己的try / catch。
“原子操作”是指一组相关的语句,例如读取文件。例如,读入内存的整个文件可能是原子操作。
答案 3 :(得分:2)
在某些有限的基础上,您可能希望将try / catch放入循环中,并在最终成功时强制中断。这可能是用于互联网访问测试,您希望用户再次尝试连接。
答案 4 :(得分:2)
像这样的东西,也许:
int MAX_RETRIES = 5;
for (var attempt=1; attempt <= MAX_RETRIES; attempt++) {
try {
DoSomethingThatMightThrow();
}
catch (AnExceptionIKnowHowToHandle) {
if (attempt < MAX_RETRIES)
continue;
throw;
}
}
答案 5 :(得分:1)
是的,有一个循环具有多次重试是很常见的,你可以在成功时突破循环。有几件事:
您可能希望在重试之前添加延迟,以便在临时问题有时间自行修复之前,您不会在几毫秒内用完所有重试。
如果你最终失败了,你应该抛出你抓到的第一个异常,而不是最后一个异常。第二个例外可能是由于第一次失败无法正确恢复而导致调试原始问题的结果。
答案 6 :(得分:1)
取决于您正在尝试的内容,但通常您希望在执行可能导致异常的代码之前检查发生异常的可能性。
例如,在访问文件之前检查文件是否存在,如果文件没有,则创建它(或其他)。
答案 7 :(得分:1)
您确定异常处理是正确的方法吗?如果您可以“解决问题”,则可以在调用异常代码之前检测错误情况。
异常处理对于真正特殊的事物来说是最自然的。失败的Internet连接(如上一个答案中所述)可以在调用异常抛出代码之前检测和处理。
答案 8 :(得分:1)
编码其他人已经提到的内容:
var success = false;
var attempts = 0;
var maxAttempts = 0;
do {
attempts++;
try {
/* your code */
success = condition;
} catch(SuperciliousException e) {
/* recover */
}
} while(!success && attempts < maxAttempts);