ほのぼの C#開発

開発の基礎から、現場で使用できるC#を掲載していきます。

C# リトライ処理

 リトライ処理

リトライする処理とエラー処理を設定するのみ。

 

責務を分けることが可能となる。

リトライの共通処理:RetryExecutor
リトライ処理   :内部処理

 

リトライ処理の呼び出し方

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


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

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

}); 

 

リトライ処理用の共通クラス

プロパティ

 ・最大リトライ回数

 ・リトライ時の待ち時間

関数

 ・リトライ実行処理(Simple) 

  ・リトライ実行処理(エラー時の対処方法)

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