65.9K
CodeProject 正在变化。 阅读更多。
Home

C# - 通用重试机制

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (13投票s)

2017 年 4 月 3 日

CPOL
viewsIcon

37408

downloadIcon

8

通用重试机制的演示

引言

在开发应用程序时,你可能需要按顺序执行一组方法来完成业务需求。如果其中一个方法发生异常,整个过程将会失败。异常可能发生在连接外部服务、网络连接问题或其他外部因素时。如果你以指定的时间间隔重试失败的过程,你可能会得到一个成功的结果,并且可以执行其余的方法。

你可以在两种不同的情况下使用重试机制:

  1. 执行方法时发生异常
  2. 方法可能没有返回预期的结果

应用程序演示

我想解释一个演示应用程序来描述重试机制的需求。

需要从main方法执行三个方法,如果失败,main方法将重试失败的方法。

/// <summary>
/// Send mail
/// </summary>
/// <returns>true/false</returns>
private static bool SendEmail()
{

    Console.WriteLine("Sending Mail ...");
    
    // simulate error
    Random rnd = new Random();
    var rndNumber = rnd.Next(1, 10);
    if (rndNumber != 3)
        throw new SmtpFailedRecipientException();
        
    Console.WriteLine("Mail Sent successfully");
    return true;
}

/// <summary>
/// Create database connection
/// </summary>
/// <returns>true/false</returns>
private static bool ConnectDatabase()
{
    Console.WriteLine("Trying to connect database ...");
    
    // simulate the error
    throw new Exception("Not able to connect database");
}

/// <summary>
/// Random number
/// </summary>
/// <returns>random number</returns>
private static int GetRandomNumber()
{
    Random rnd = new Random();
    // Generate the random number between 1-10
    var result = rnd.Next(1, 10);
    
    Console.WriteLine(result.ToString());
    
    return result;
}

static void Main(string[] args)
{
    // Send mail with 10 retries
    Console.WriteLine("Send mail, if it fails then try 10 times");
    
    var isSuccess = Retry.Execute(() => SendEmail(), new TimeSpan(0, 0, 1), 10, true);            
    
    if (!isSuccess)
        Console.WriteLine("Unable to send a mail");
        
    // Connect database
    var connectionStatus = Retry.Execute(() => ConnectDatabase(), new TimeSpan(0, 0, 2), 5, true);
    if (!connectionStatus)
        Console.WriteLine("Unable connect database");
        
    // Print Random number till the random number is 4
    Console.WriteLine("Print Random number till the random number is 4");
    Retry.Execute(() => GetRandomNumber(), new TimeSpan(0, 0, 1), 10, 4);
    
    Console.ReadLine();
}

以下是在不同情况下实现重试机制的方法。

输出

通用重试类

public class Retry
    {
        /// <summary>
        /// Generic Retry
        /// </summary>
        /// <typeparam name="TResult">return type</typeparam>
        /// <param name="action">Method needs to be executed</param>
        /// <param name="retryInterval">Retry interval</param>
        /// <param name="retryCount">Retry Count</param>
        /// <param name="expectedResult">Expected Result</param>
        /// <param name="isExpectedResultEqual">true/false to check equal 
        /// or not equal return value</param>
        /// <param name="isSuppressException">
        /// Suppress exception is true / false</param>
        /// <returns></returns>
        public static TResult Execute<TResult>(
          Func<TResult> action,
          TimeSpan retryInterval,
          int retryCount,
          TResult expectedResult,
          bool isExpectedResultEqual = true,
          bool isSuppressException = true
           )
          {
            TResult result = default(TResult);

            bool succeeded = false;
            var exceptions = new List<Exception>();

            for (int retry = 0; retry < retryCount; retry++)
            {
                try
                {
                    if (retry > 0)
                        Thread.Sleep(retryInterval);
                    // Execute method
                    result = action();

                    if (isExpectedResultEqual)
                        succeeded = result.Equals(expectedResult);
                    else
                        succeeded = !result.Equals(expectedResult);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }

                if (succeeded)
                    return result;
            }

            if (!isSuppressException)
                throw new AggregateException(exceptions);
            else
                return result;
        }
    }
© . All rights reserved.