1
1

More than 1 year has passed since last update.

VSCodeでC#(例外発生時のリトライ処理)

Posted at

はじめに

Visual Studioをインストールして開発しようとすると時間がかかるのでVSCodeでお手軽に
しかし、最新環境では開発していないからHello World動かすだけでもはまるという...

参考サイト

◆.NET ダウンロード (Linux、macOS、Windows)
 https://dotnet.microsoft.com/ja-jp/download/dotnet
  ※【.NET6.0】をクリックして、Windowsのx64をダウンロード
   dotnet-sdk-6.0.408-win-x64.exe
  ※【.NET7.0】をクリックして、Windowsのx64をダウンロード
   dotnet-sdk-7.0.203-win-x64.exe
◆C#の拡張機能(ms-dotnettools.csharp)インストール
 https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp

environment.bat
> dotnet --version
7.0.203
> dotnet new console --use-program-main --target-framework-override net472

※.cs/.csprojを修正

> dotnet run
Hello, World!

◆ODP.NET+C#でOracleに接続する
 https://qiita.com/wakasama_pcmaster/items/a81d131f742f0f6e7104
  ※とりあえず試すための環境構築ネタ


◆C# コンソール アプリ テンプレートで最上位レベルのステートメントが生成される
 https://learn.microsoft.com/ja-jp/dotnet/core/tutorials/top-level-templates
  ※.NET SDK 6.0.300 以降では、consoleテンプレートにはオプションがあります
   --use-program-main
   これを使用して、最上位レベルのステートメントを使用せず、
   メソッドを持つコンソール プロジェクトを Main 作成します。
◆VSCodeで.NET Frameworkを利用する。-.NET Framework利用のための手続き - Technically Impossible
 https://impsbl.hatenablog.jp/entry/VSCodeWithDNFW2


◆[コード]リトライ処理
 https://free-creators.com/retry-proc/
  ※これが一番シンプルだが...
◆C# 再試行パターンを実装する
 https://shikaku-sh.hatenablog.com/entry/c-sharp-implements-retry-pattern
  ※説明~テストまで解説してくれている
◆C#でリトライ処理を共通化してみた
 https://qiita.com/t_takahari/items/6367434c3484b29cf14d
◆エラーが起こった時にリトライする を一般化したコードを書いてみる
 https://qiita.com/Marimoiro/items/b0282792077ab2966135
◆例外発生時にリトライする
 https://blog.xin9le.net/entry/2013/09/08/173009


◆C#でアプリケーション設定を取得・保存する、いくつかの方法
 https://seraphy.hatenablog.com/entry/20120708/p1
◆【C# 10.0】ファイル スコープ名前空間 (一斉置換設定)
 https://ufcpp.net/blog/2021/11/fix-all-file-scoped-namespace/
  ※名前空間を namespace N {} からファイル スコープな namespace N; に書き換え
   ImplicitUsings を true にして未使用 using になる部分をごっそり削除
  ※.editorconfig設定で一斉置換可能らしい...

コード

RetryOperation.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
  </ItemGroup>
</Project>
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="MaxRetryCount" value="3" />
        <add key="RetrySleepTime" value="5000" />
    </appSettings>
</configuration>
RetryHelper.cs
namespace RetryOperation {

    using System;
    using System.Configuration;
    
    public static class RetryHelper
    {
        // 条件に合う場合は指定回数以内で再試行し、それ以外の場合はエラー処理
        public static void RetryIfError(Action onAction, Action<Exception> onError, Func<Exception, bool> retryCondition, uint maxRetryCount)
        {
            if (onAction == null)       throw new ArgumentNullException("onAction");
            if (onError == null)        throw new ArgumentNullException("onError");
            if (retryCondition == null) throw new ArgumentNullException("retryCondition");
            RetryHelper.RetryIfErrorCore(onAction, onError, retryCondition, maxRetryCount);
        }

        // コアロジック
        private static void RetryIfErrorCore(Action onAction, Action<Exception> onError, Func<Exception, bool> retryCondition, uint? retryCount)
        {
            if (onError == null)        onError        = ex => {};
            if (retryCondition == null) retryCondition = ex => true;

            int maxRetryCount = int.Parse(ConfigurationManager.AppSettings["MaxRetryCount"]);
            int RetrySleepTime = int.Parse(ConfigurationManager.AppSettings["RetrySleepTime"]);

            for (var retryNumber = 0; retryNumber < maxRetryCount; retryNumber++)
            {
                try
                {
                    onAction();
                }
                catch (Exception ex)
                {
                    if (retryCondition(ex))
                    {
                        if (!retryCount.HasValue)       continue;
                        if (count++ < retryCount.Value) continue;
                    }
                    onError(ex);
                }
            }
        }
    }
}
Program.cs
namespace RetryOperation {

    using System;
    using System.Runtime.ExceptionServices;

    class Program
    {
        static void Main(string[] args)
        {
            // ループカウンタ
            int retryCount = 0;

            RetryHelper.RetryIfError(() =>
            {
                //--- 失敗したら困る処理

                // DB保存メソッド呼び出し(失敗)
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("DB保存実行!!{0}回目", ++retryCount);
                if(retryCount < 3){
                    throw new InvalidOperationException();
                }
            },
            exstack =>
            {
                //--- エラー処理
                ExceptionDispatchInfo.Capture(exstack).Throw(); //--- スタックトレース維持
            },
            ex => ex is InvalidOperationException,  //--- 条件
            5);                                     //--- 再試行回数
        }
    }
}
1
1
0

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
1
1