1

我经常遇到一些情况,如果某些操作失败,我必须重试,在一定次数后放弃,并在尝试之间稍作休息。

有没有办法创建一个“重试方法”,让我每次这样做时都不会复制代码?

4

2 回答 2

3

厌倦了一遍又一遍地复制/粘贴相同的代码,所以我创建了一个方法来接受必须完成的任务的委托。这里是:

//  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。所以我想我的例子对你还是有用的。

于 2012-06-25T13:55:25.420 回答
1

我已经根据特定的领域要求创建了这样的帮助程序,但作为一个通用的起点,请看一下 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

于 2012-06-25T14:08:23.150 回答