プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

ReactiveExtensionsのThrottleの中でOnNextを呼んではいけない

はいやらかしました

まずはこちらのコードでどうなるか

static Subject<int> _subject;
static void Main(string[] args)
{
    _subject = new Subject<int>();
    _subject.Subscribe(Func);
    _subject.OnNext(0);

    Console.ReadKey();
}
static void Func(int i)
{
    Console.WriteLine(i);
    if (i >= 10) return;
    _subject.OnNext(i + 1);
}

コンソールに0から10まで出力されます。問題無しです

つぎにSubscribeの前にThrottleを入れて試してみます

// 他は同じなので割愛
    _subject.Throttle(TimeSpan.FromSeconds(1)).Subscribe(Func);

コンソールには0しか出力されません

なぜか、はThrottleのソースを見ればすぐにわかります

github.com

上記リンクのOnNext_hasValue = true;としてその次のPropagate内のForwardOnNextの後でfalseにしています ForwardOnNextの先に私が書いたFuncがいるわけで、その関数を抜けた後に_hasValue = false;にしているのだからFunc内でいくら次の値を発行しても無視されます

(説明下手は読み手の想像力でカバーしてください)

Throttle後は別スレッドになるのは知っていたので呼びっぱなしで次を処理しているものだと思い込んでいました。反省。

「処理の失敗時に少し待ってリトライ」みたいな時に↑みたいな感じで書いてしまうんですよねー