私の目標は、更新ハンドラーが "Type2" オブジェクトに対して 5 秒に 1 回しか呼び出されないようにすることです。オブザーバブルは 5 秒ごとに複数の値を生成しますが、最後に処理された更新から 5 秒以内に発生する値はすべて無視したいと考えています。
ここでこの質問をしました: 特定の条件が満たされた場合にのみスロットル
と、良い反響を得ました。Observable.Window を使用して目標を達成しようとしました。私はそれが機能していると思っていましたが、ウィンドウが閉じる直前に最初の更新が行われ(更新が処理される)、次のウィンドウが開くと別の更新が到着して処理されると、誤った出力が生成される可能性があることが判明しました。最後に処理された更新から 5 秒以内に届いたので、そうしたくありません。
リンクのコードからわずかに変更された、問題を示すコードを次に示します。
var source = new Subject<Thing>();
var feed = source.Publish().RefCount();
var ofType1 = feed.Where(t => t.ActivationType == "Type1");
var ofType2 = feed
.Where(t => t.ActivationType == "Type2")
.Window(() =>
Observable.Timer(TimeSpan.FromSeconds(5))
.Do(t => Console.WriteLine("\nTICK: " + DateTime.Now.ToString("hh:mm:ss:fff"))))
.Select(x => x.Take(1))
.Merge()
.Do(t => Console.WriteLine("A new window opened " + DateTime.Now.ToString("hh:mm:ss:fff")));
var query = ofType1.Merge(ofType2);
query.Subscribe(t => Console.WriteLine("UPDATE: " + t.ID + " " + DateTime.Now.ToString("hh:mm:ss:fff")));
int msDelay = 3000;
Task task = Task.Factory
.StartNew(() => { Thread.Sleep(msDelay); })
.ContinueWith((Task starter) =>
{
while (running)
{
var thing = new Thing(); //Note that all Things are by default Type2
source.OnNext(thing);
Thread.Sleep(100);
}
}, TaskContinuationOptions.LongRunning);
Console.ReadLine();
したがって、サブスクリプションが作成され、サブスクリプションが作成されると、ウィンドウで使用される Observable.Timer が開始されます。値を生成するために使用される while ループは、3000 ミリ秒の遅延の後まで開始されません。
出力は次のようになります。
A new window opened 03:48:03:725
UPDATE: 1ac54fb3-f73d-4840-b4d8-95d4250ce65d 03:48:03:752
TICK: 03:48:05:714
A new window opened 03:48:05:754
UPDATE: 12d36e53-010f-4ccd-b9f8-2951b085f88c 03:48:05:754
TICK: 03:48:10:730
A new window opened 03:48:10:755
UPDATE: 25d84e72-94f9-4f50-83f4-14c1004c10fa 03:48:10:755
TICK: 03:48:15:738
A new window opened 03:48:15:755
UPDATE: 5f32b7d5-196f-445c-bf25-5c362b2fd6f0 03:48:15:755
TICK: 03:48:20:747
A new window opened 03:48:20:756
UPDATE: e3a3a30d-8031-41b5-b115-499dbe91aaf7 03:48:20:756
TICK: 03:48:25:755
A new window opened 03:48:25:756
UPDATE: 239fb25b-5135-463b-bf7e-5728ffa07f5c 03:48:25:756
ご覧のとおり、最初の Type2 更新はウィンドウが開いている間に行われるため、処理されます。次に、2 秒後、ウィンドウのタイマーが作動し、新しいウィンドウが開きます。それはすぐに次の Type2 更新を処理しますが、これは望んでいません。その後、正常に動作しているように見えます (Window 宣言で定義されているように、5 秒ごとに更新されます)。
5 秒 (または選択した時間枠) ごとに 1 つの更新のみが処理されるようにするために使用できる方法または別の方法はありますか?