リトライ処理を実施する際に利用するRetryExecutorについて紹介します。

使用方法
-------------------------------------------------------------------------------
            //------------------------------------------
            // リトライ用の実行クラスの生成
            //------------------------------------------
            _executor = new RetryExecutor(new RetryPolicy()
            {
                MaxRetryNum = CommonData.Instance.RetryCount,
                RetrySleep = CommonData.Instance.RetryWaitSecond * 1000
            });


            //------------------------------------------
            // リトライ処理実行
            //------------------------------------------
            var result = _executor.Execute(() =>
            {
//  繰り返し実行したい処理を記載

                return trendData;
 }, ex =>
            {
                // エラー処理

            }); 


-------------------------------------------------------------------------------

using System;
using System.Threading;

namespace Common
{
    /// <summary>
    /// リトライ処理が必要な場合の、リトライのルールを定義する抽象クラスです。
    /// </summary>
    public class RetryPolicy
    {
        /// <summary>
        /// 最大リトライ回数
        /// </summary>
        public int MaxRetryNum { get; set; }

        /// <summary>
        /// リトライ時のベースとなる処理停止時間(ミリ秒)
        /// </summary>
        public int RetrySleep { get; set; }
    }

    /// <summary>
    /// リトライ処理が必要な箇所で指定された条件によってリトライを行うためのクラスです。
    /// </summary>
    public class RetryExecutor
    {
        private readonly RetryPolicy _policy;

        /// <summary>
        /// リトライルールを受け取ってインスタンスを生成します。
        /// </summary>
        /// <param name="policy"></param>
        public RetryExecutor(RetryPolicy policy)
        {
            _policy = policy;
        }

        /// <summary>
        /// リトライをかけながら指定された処理を実行します。
        /// </summary>
        /// <param name="executeAction">実行する処理</param>
        public virtual void Execute(Action executeAction)
        {
            for (var retryNum = 1; retryNum <= _policy.MaxRetryNum + 1; retryNum++)
            {
                try
                {
                    executeAction();
                    break;
                }
                catch (Exception ex)
                {
                    Loggers.Log.Error(ex.ToString());

                    if (retryNum > _policy.MaxRetryNum)
                    {
                        throw new Exception(string.Format("リトライ回数をオーバーしたため、処理を終了します。最大リトライ回数:{0}", (_policy.MaxRetryNum).ToString()));
                    }

                    Loggers.Log.Warn(string.Format("一定時間[{0}ミリ秒]待機した後、リトライします。リトライ回数:{1}", _policy.RetrySleep.ToString(), retryNum.ToString()));
                    Thread.Sleep(_policy.RetrySleep);
                }
            }
        }

        /// <summary>
        /// リトライをかけながら指定された処理を実行します。
        /// </summary>
        /// <param name="executeAction">実行する処理</param>
        /// <param name="errorAction">処理実行時に発生したエラー処理</param>
        public virtual T Execute<T>(Func<T> executeAction, Action<Exception> errorAction = null)
        {
            var result = default(T);
            for (var retryNum = 1; retryNum <= _policy.MaxRetryNum + 1; retryNum++)
            {
                try
                {
                    result = executeAction();
                    break;
                }
                catch (Exception ex)
                {
                    Loggers.Log.Error(ex.ToString());

                    if (errorAction != null)
                    {
                        errorAction(ex);
                    }

                    if (retryNum > _policy.MaxRetryNum)
                    {
                        throw new Exception(string.Format("リトライ回数をオーバーしたため、処理を終了します。最大リトライ回数:{0}", (_policy.MaxRetryNum).ToString()));
                    }

                    Loggers.Log.Warn(string.Format("一定時間[{0}ミリ秒]待機した後、リトライします。リトライ回数:{1}",_policy.RetrySleep.ToString(), retryNum.ToString()));
                    Thread.Sleep(_policy.RetrySleep);
                }
            }

            return result;
        }
    }
}