Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C#

C# - Generic Retry Mechanism

Rate me:
Please Sign up or sign in to vote.
4.74/5 (13 votes)
3 Apr 2017CPOL 35.4K   6   20   5
Demo for generic retry mechanism

Introduction

When you develop an application, you may have to execute a set of methods in sequential order to complete the business requirements. If you got an exception from one of the methods, the entire process will fail. The exception may occur when you connect the external services or network connection issue or other external factors. If you retry the failure process with specified interval, you may get a success result and you can execute the rest of the methods.

You can use the retry mechanism in two different situations:

  1. Getting exception when you execute a method
  2. A method may not return an expected result

Application Demo

I want to explain one demo application to describe the need of retry mechanism.

There are three methods needed to execute from the main method, if it fails, the main method will retry the failed methods.

C#
/// <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();
}

Here are the ways to implement the Retry mechanism in different situations.

Image 1

Output

Image 2

Generic Retry Class

C#
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;
        }
    }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) cognizant
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhat if I need to pass parameters to this generic method like different type of parameters Pin
Rajdatta Mahajan12-Sep-18 19:30
Rajdatta Mahajan12-Sep-18 19:30 
QuestionWhat Happens if Action Returns Void? Pin
Member 1028714012-Apr-18 1:08
Member 1028714012-Apr-18 1:08 
QuestionNice! Pin
David Catriel10-Apr-17 5:18
David Catriel10-Apr-17 5:18 
QuestionGood Retry example Pin
Tridip Bhattacharjee3-Apr-17 22:29
professionalTridip Bhattacharjee3-Apr-17 22:29 
Questionor just use this Pin
Sacha Barber3-Apr-17 3:56
Sacha Barber3-Apr-17 3:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.