過去記事インデックス
- Reactive Extensions再入門 その1
- Reactive Extensions再入門 その2「IObservableインターフェースとIObserverインターフェース」
- Reactive Extensions再入門 その3「IObservableのファクトリメソッド」
- Reactive Extensions再入門 その4「Timer系のファクトリメソッド」
- Reactive Extensions再入門 その5「HotとCold」
- Reactive Extensions再入門 その6「HotなIObservableを作成するファクトリ」
- Reactive Extensions再入門 その7「LINQスタイルの拡張メソッド」
- Reactive Extensions再入門 その8「SkipとTakeメソッド」
- Reactive Extensions再入門 その9「Skip + Take + Repeat = ドラッグ」
- Reactive Extensions再入門 その10「Doメソッド」
- Reactive Extensions再入門 その11「Catchメソッド」
- Reactive Extensions再入門 その12「Finallyメソッドとリソース解放」
- Reactive Extensions再入門 その13「最後の値を取得するLatestとMostRecentメソッド」
- Reactive Extensions再入門 その14「Nextメソッド」
- Reactive Extensions再入門 その15「To*****系メソッド」
- Reactive Extensions再入門 その16「最大、最少、平均を求めるメソッド」
- Reactive Extensions再入門 その17「集計するメソッド」
- Reactive Extensions再入門 その18「CountメソッドとLongCountメソッド」
- Reactive Extensions再入門 その19「AnyメソッドとAllメソッド」
- Reactive Extensions再入門 その20「GroupByメソッドでグルーピングしてみよう」
- Reactive Extensions再入門 その21「GroupByUntilメソッド」
- Reactive Extensions再入門 その22「単一の値を取得するメソッド」
- Reactive Extensions再入門 その23「重複を排除するメソッド」
- Reactive Extensions再入門 その24「単一の値を取得するメソッド その2」
- Reactive Extensions再入門 その25「値をまとめるBufferメソッド」
- Reactive Extensions再入門 その26「値をまとめるWindowメソッド」
- Reactive Extensions再入門 その27「時間でフィルタリング?Sampleメソッド」
- Reactive Extensions再入門 その28「落ち着いたら流すThrottleメソッド」
- Reactive Extensions再入門 その29「値を指定した時間だけ遅延させるDelayメソッド」
- Reactive Extensions再入門 その30「もう待ちきれない!を表現するTimeoutメソッド」
- Reactive Extensions再入門 その31「時間に関する情報を付与するTimestampとTimeIntervalメソッド」
- Reactive Extensions再入門 その32「型変換を行うCastとOfTypeメソッド」
- Reactive Extensions再入門 その33「シーケンスの最後を起点にSkipとTake」
- Reactive Extensions再入門 その34「ダメなら次の人!を実現するOnErrorResumeNextメソッド」
はじめに
前回のOnErrorResumeNextメソッドでは、エラーの場合は別の方法で再開するという処理をやりました。今回は、同じことを愚直にやり続けるRetryメソッドです!
Retryメソッド
ここではRetryメソッドについて説明します。Retryメソッドは名前の通りエラーが起きた場合に、繰り返し同じ処理を行うメソッドです。メソッドのオーバーロードには、成功するまで無限に繰り返しリトライをするものと、引数でリトライ回数を指定するものがあります。メソッドのシグネチャを下記に示します。
public static IObservable<T> Retry<T>(this IObservable<T> source); public static IObservable<T> Retry<T>(this IObservable<T> source, int retryCount);
まず、無限に繰り返すメソッドのオーバーロードを使ったコード例を下記に示します。
var retryCount = 0; Observable // retryCountが3になるまでエラーになる .Create<string>(o => { Console.WriteLine("Create method called: {0}", retryCount); if (retryCount == 3) { o.OnNext(retryCount.ToString()); o.OnCompleted(); return Disposable.Empty; } retryCount++; o.OnError(new InvalidOperationException(retryCount.ToString())); return Disposable.Empty; }) // 成功するまでリトライする .Retry() // 購読 .Subscribe( s => Console.WriteLine("OnNext: {0}", s), ex => Console.WriteLine("OnError: {0}", ex), () => Console.WriteLine("OnCompleted"));
Createメソッドで3回目までエラーになるIObservable
Create method called: 0 Create method called: 1 Create method called: 2 Create method called: 3 OnNext: 3 OnCompleted
Createメソッドが4回呼ばれてエラーではない値が発行されるとSubscribeまで値が渡っていることが確認できます。このようにエラーが起きても何度もリトライします。
次にリトライ回数を指定した場合の動作を示すコード例を下記に示します。
var retryCount = 0; Observable // retryCountが3になるまでエラーになる .Create<string>(o => { Console.WriteLine("Create method called: {0}", retryCount); if (retryCount == 3) { o.OnNext(retryCount.ToString()); o.OnCompleted(); return Disposable.Empty; } retryCount++; o.OnError(new InvalidOperationException(retryCount.ToString())); return Disposable.Empty; }) // 2回リトライする .Retry(2) // 購読 .Subscribe( s => Console.WriteLine("OnNext: {0}", s), ex => Console.WriteLine("OnError: {0}", ex), () => Console.WriteLine("OnCompleted"));
先ほどと、ほぼ同じコードですがRetryメソッドの引数で2回までしかリトライをしないように指定しています。このコードの実行結果を以下に示します。
Create method called: 0 Create method called: 1 OnError: System.InvalidOperationException: 2
実行結果からわかるように2回目のリトライでも例外が発生しているため、SubscribeのOnErrorが呼び出されています。おそらく、現実的にはリトライ回数を指定するオーバーロードを使うことが多くなると思います。