5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C#でリトライ制御を共通化したい

Posted at

1. はじめに

  • DBの関連処理などリトライするケースが発生したので、処理を共通化したい
  • メソッドの戻り値の有無があるので、どちらにも対応したい
  • リトライ回数、リトライ間隔を設定できるようにしたい

2. 開発環境

  • C#
  • .Net 6
  • Visual Studio 2022
  • Windows 11

3. ソースコード

*Staticなユーティリティクラスを準備する

RetryExecteUtil.cs
/// <summary>
/// リトライ処理を行うユーティリティクラス
/// </summary>
public class RetryExecteUtil
{
    /// <summary>
    /// 処理を実行する
    /// 例外が発生した場合は指定秒数間隔でリトライする
    /// </summary>
    /// <typeparam name="T">リトライ対象メソッドの戻り値(型)</typeparam>
    /// <param name="retryMaxCount">最大リトライ回数</param>
    /// <param name="retryInterval">リトライ間隔(ミリ秒)</param>
    /// <param name="action">リトライ対象メソッド(戻り値あり)</param>
    /// <returns>処理結果</returns>
    public static T Execute<T>(int retryMaxCount, int retryInterval, Func<T> action)
    {
        // パラメータチェック
        if (retryMaxCount < 0)
        {
            // 最大リトライ回数
            throw new ArgumentOutOfRangeException("retryMaxCount");
        }
        if (retryInterval < 0)
        {
            // リトライ間隔
            throw new ArgumentOutOfRangeException("retryInterval");
        }
        if (action == null)
        {
            // 処理
            throw new ArgumentNullException("action");
        }

        /// <summary>
        /// リトライ回数をカウントします
        /// </summary>
        int retryCount = 0;

        while (true)
        {
            try
            {
                // メソッド
                return action();
            }
            catch (Exception)
            {
                // リトライが必要な処理で例外が発生した場合
                // 指定回数リトライ
                if (retryCount++ < retryMaxCount)
                {
                    // 最大リトライ回数に達していない場合
                    Thread.Sleep(retryInterval);
                }
                else
                {
                    // 最大リトライ回数に達した場合
                    throw;
                }
            }
        }
    }

    /// <summary>
    /// 処理を実行する
    /// 例外が発生した場合は指定秒数間隔でリトライする
    /// </summary>
    /// <param name="retryMaxCount">最大リトライ回数</param>
    /// <param name="retryInterval">リトライ間隔(ミリ秒)</param>
    /// <param name="action">リトライ対象メソッド(戻り値なし)</param>
    public static void Execute(int retryMaxCount, int retryInterval, Action action)
    {

        // パラメータチェック
        if (retryMaxCount < 0)
        {
            // 最大リトライ回数
            throw new ArgumentOutOfRangeException("retryMaxCount");
        }
        if (retryInterval < 0)
        {
            // リトライ間隔
            throw new ArgumentOutOfRangeException("retryInterval");
        }
        if (action == null)
        {
            // 処理
            throw new ArgumentNullException("action");
        }

        /// <summary>
        /// リトライ回数をカウントします
        /// </summary>
        int retryCount = 0;

        while (true)
        {
            try
            {
                action();
                break;
            }
            catch (Exception)
            {
                // リトライが必要な処理で例外が発生した場合
                // 指定回数リトライ

                if (retryCount++ < retryMaxCount)
                {
                    // 最大リトライ回数に達していない場合
                    Thread.Sleep(retryInterval);
                }
                else
                {
                    // 最大リトライ回数に達した場合
                    throw;
                }
            }
        }
    }
}

4. 使用方法

4.1. リトライ処理メソッド

var class1 = new Class1();

// 戻り値なしの場合
RetryExecteUtil.Execute(5,1000,()=> class1.RetryVoidMethod());

// 戻り値ありの場合
Debug.Print(RetryExecteUtil.Execute(5,1000,()=> class1.RetryReturnMethod("OK")));

4.2. リトライ対象クラス、メソッド

Class1.cs
public class Class1
{
    int _count1 = 0;
    int _count2 = 0;

    public void RetryVoidMethod()
    {
        _count1++;

        if (_count1 < 5)
        {
            Debug.Print($"Exception {_count1}");
            throw new Exception();
        }
    }

    public string RetryReturnMethod(string s)
    {
        
        _count2++;

        if (_count2 < 5)
        {
            Debug.Print($"Exception {_count2}");
            throw new Exception();
        }

        return s;
    }

}

4.3 動作確認

デバッグ出力で動作を確認した
Exception 1
例外がスローされました: 'System.Exception'
Exception 2
例外がスローされました: 'System.Exception'
Exception 3
例外がスローされました: 'System.Exception' 
Exception 4
例外がスローされました: 'System.Exception'
Exception 1
例外がスローされました: 'System.Exception'
Exception 2
例外がスローされました: 'System.Exception'
Exception 3
例外がスローされました: 'System.Exception'
Exception 4
例外がスローされました: 'System.Exception'
OK

5. 参考文献

5
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?