Dot-Net
反應式擴展:節流/樣本與不同的時間間隔
我有一個
IObservable以隨機間隔產生值的,我想限制這個序列。我發現的一件事是Throttle運營商對“節流”的定義與我的不同。
Throttle僅在指定的時間間隔過後才產生值**(**它產生最後看到的值)。我認為節流意味著在指定的時間間隔內產生值(當然,除非有沉默)。說,我希望
Observable.Interval(100).Select((_,i) => i).Throttle(200)產生(以任何性能/時序問題為模)偶數,因為我將其限制為“半速”。然而,這個序列根本沒有產生任何價值,因為從來沒有一段長度為 200 的靜默期。所以,我發現這
Sample實際上是我想要的“節流”行為。Observable.Interval(100).Select((_,i) => i).Sample(200)產生(再次以任何性能/時序問題為模)偶數序列。但是,我還有另一個問題:間隔會有所不同,具體取決於最後一個“採樣”值。我想要的是編寫一個如下所示的運算符:
public static IObservable<T> Sample<T>(this IObservable<T> source, Func<T, TimeSpan> intervalSelector);該
intervalSelector參數產生下一個樣本的間隔,第一個樣本……要麼取自第一個值,要麼取自附加參數,我不在乎。我試著寫這個,但我最終得到了一個大而復雜的結構,它不能很好地工作。我的問題是,我可以使用現有的運營商(也就是單線)來建構它嗎?
幾個小時後,在上面睡了一會兒,我明白了。
public static IObservable<T> Sample<T>(this IObservable<T> source, Func<T, TimeSpan> intervalSelector) { return source.TimeInterval() .Scan(Tuple.Create(TimeSpan.Zero, false, default(T)), (acc, v) => { if(v.Interval >= acc.Item1) { return Tuple.Create(intervalSelector(v.Value), true, v.Value); } return Tuple.Create(acc.Item1 - v.Interval, false, v.Value); }) .Where(t => t.Item2) .Select(x => x.Item3); }這可以按我的意願工作:每次它產生一個 value
x時,它都會停止產生值,直到intervalSelector(x)時間過去。