我经常遇到一些情况,如果某些操作失败,我必须重试,在一定次数后放弃,并在尝试之间稍作休息。
有没有办法创建一个“重试方法”,让我每次这样做时都不会复制代码?
厌倦了一遍又一遍地复制/粘贴相同的代码,所以我创建了一个方法来接受必须完成的任务的委托。这里是:
// logger declaration (I use NLog)
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
delegate void WhatTodo();
static void TrySeveralTimes(WhatTodo Task, int Retries, int RetryDelay)
{
int retries = 0;
while (true)
{
try
{
Task();
break;
}
catch (Exception ex)
{
retries++;
Log.Info<string, int>("Problem doing it {0}, try {1}", ex.Message, retries);
if (retries > Retries)
{
Log.Info("Giving up...");
throw;
}
Thread.Sleep(RetryDelay);
}
}
}
要使用它,我会简单地写:
TrySeveralTimes(() =>
{
string destinationVpr = Path.Combine(outdir, "durations.vpr");
File.AppendAllText(destinationVpr, file + ", " + lengthInMiliseconds.ToString() + "\r\n");
}, 10, 100);
在此示例中,我正在附加一个文件,该文件被某个外部进程锁定,编写它的唯一方法是重试几次,直到该进程完成...
我肯定希望看到处理这种特定模式(重试)的更好方法。
编辑:我在另一个答案中查看了Gallio,它真的很棒。看这个例子:
Retry.Repeat(10) // Retries maximum 10 times the evaluation of the condition.
.WithPolling(TimeSpan.FromSeconds(1)) // Waits approximatively for 1 second between each evaluation of the condition.
.WithTimeout(TimeSpan.FromSeconds(30)) // Sets a timeout of 30 seconds.
.DoBetween(() => { /* DoSomethingBetweenEachCall */ })
.Until(() => { return EvaluateSomeCondition(); });
它无所不能。它甚至会在您编写代码时看着您的孩子 :) 但是,我力求简单,并且仍在使用 .NET 2.0。所以我想我的例子对你还是有用的。
我已经根据特定的领域要求创建了这样的帮助程序,但作为一个通用的起点,请看一下 Gallio 的实现。
http://www.gallio.org/api/html/T_MbUnit_Framework_Retry.htm
https://code.google.com/p/mb-unit/source/browse/trunk/v3/src/MbUnit/MbUnit/Framework/Retry.cs
http://interfacingreality.blogspot.co.uk/2009/05/retryuntil-in-mbunit-v3.html