O'Reilly『C#クックブック』 p.96「レシピ3.9 信頼性の高いネットワーク通信を構築する」が勉強になったのでまとめる。
p.96-97よりソースコード引用+本記事用にコメント
例外をスローするメソッド
static async Task GetOrdersAsync(){
//取り出した例外オブジェクトをスロー
//Taskクラスによって完了済みのタスクを作成
throw await Task.FromResult (
new HttpRequestException (
"Timeout", null, HttpStatusCode.RequestTimeout));
}
HttpRequestExceptionクラス
HttpClient と HttpMessageHandler クラスによってスローされる例外の基本クラス。
HTTPリクエストに失敗した場合に発生する。
Taskクラス
非同期操作を表すクラス。
ネットワークエラーを処理
public static await Task Main(){
//処理中に例外が発生した時の待機ミリ秒を設定
const int DelayMilliseconds = 500;
//処理中に例外が発生した時の再接続リトライ回数を設定
const int RetryCount = 3;
bool success = false;
int tryCount = 0;
try {
do {
//tryを2重入れ子にする
try {
Console.WriteLine("注文を取得中");
await GetOrdersAsync();
success = true;
break;
} catch (HttpRequestException hre) {
when (hre.StatusCode == HttpStatusCode.RequestTimeout)
}
//処理にトライした回数を1インクリメント
tryCount++;
int millsecondsToDelay = DelayMilliseconds * tryCount;
Console.WriteLine($"処理中に例外が発生しました -" +
$"{millisexondToDelay}ミリ秒待機します");
//待ち
await Task.Delay(millisecondsToDelay);
//リトライする回数の上限まで繰り返し処理にトライ
} while (tryCount < RetryCount);
//リトライした結果、処理の成功/失敗を判別
} finally {
if(success == true){
Console.WriteLine("処理が成功しました");
} else {
Console.WriteLine("処理が失敗しました");
}
}
}
結果(例)
注文を取得中
処理中に例外が発生しました - 500 ミリ秒待機します
注文を取得中
処理中に例外が発生しました - 1000 ミリ秒待機します
注文を取得中
処理中に例外が発生しました - 1500 ミリ秒待機します
処理が失敗しました
使用シーン
-
通信が安定しないバックエンドサービスと連携するアプリケーションと通信を行う際、処理が失敗しないように指定回数通信に失敗しても処理をリトライさせたい時。
-
一部のサードパーティー製APIはクライアントのリクエスト回数を制限していることがあり、リクエストを即座に繰り返すとすぐに回数を超過してしまうことになる
- このように、処理に失敗した時に一定時間保留するような実装にするとよい