下面的代码显示了在捕获异常时尝试封装逻辑以重新运行某些内容。
是否存在模式或其他内容?或者您对该代码有什么改进建议?
public static void DoWhileFailing(int triesAmount, int pauseAmongTries, Action codeToTryRun) {
bool passed = false;
Exception lastException = null;
for (int i = 0; !passed && i < triesAmount; i++) {
try {
if (i > 0) {
Thread.Sleep(pauseAmongTries);
}
codeToTryRun();
passed = true;
} catch(Exception e) {
lastException = e;
}
}
if (!passed && lastException != null) {
throw new Exception(String.Format("Something failed more than {0} times. That is the last exception catched.", triesAmount), lastException);
}
}
答案 0 :(得分:3)
我会重写这个以消除一些变量,但一般来说你的代码没问题:
public static void DoWhileFailing(int triesAmount, int pauseAmongTries, Action codeToTryRun) {
if (triesAmount<= 0) {
throw new ArgumentException("triesAmount");
}
Exception ex = null;
for (int i = 0; i < triesAmount; i++) {
try {
codeToTryRun();
return;
} catch(Exception e) {
ex = e;
}
Thread.Sleep(pauseAmongTries);
}
throw new Exception(String.Format("Something failed more than {0} times. That is the last exception catched.", triesAmount, ex);
}
答案 1 :(得分:1)
我写了下面的代码来做基本相同的事情。它还允许您指定要捕获的Exception的类型,以及确定当前迭代是否应抛出异常或继续重试的Func
。
public static void RetryBeforeThrow<T>(
this Action action,
Func<T, int, bool> shouldThrow,
int waitTime) where T : Exception
{
if (action == null)
throw new ArgumentNullException("action");
if (shouldThrow == null)
throw new ArgumentNullException("shouldThrow");
if (waitTime <= 0)
throw new ArgumentException("Should be greater than zero.", "waitTime");
int tries = 0;
do
{
try
{
action();
return;
}
catch (T ex)
{
if (shouldThrow(ex, ++tries))
throw;
Thread.Sleep(waitTime);
}
}
while (true);
}
然后你就可以这样称呼它
Action a = () =>
{
//do stuff
};
a.RetryBeforeThrow<Exception>((e, i) => i >= 5, 1000);
您可以指定任何异常类型,并且可以检查Func
中的异常以确定它是否是您要抛出或继续重试的异常。这使您能够在Action
中抛出自己的异常,以阻止重试的发生。
答案 2 :(得分:1)
我没有看到代码有任何问题,我只会质疑你的假设。
我看到了几个问题:
根据您的需要,您的代码可能就足够了,但是为了更好地封装不可靠的资源,请查看circuit breaker模式。