2012-07-25 58 views
4

我有一個事件每秒鐘(可能)觸發(計時器滴答)。我想要做的是每60秒取最後一個勾號的EventArgs值(如果在這60秒內有新的勾號)。我試圖做類似:使用Rx,每60秒採取一次最後觸發的事件

Observable.FromEventPattern(
    h => myThing.SomeEvent += h, 
    h => myThing.SomeEvent -= h) 
     .Throttle(TimeSpan.FromSeconds(60)) 
     .TakeLast(1) 
     .Do(p => // do something with p); 

不幸的是我從來沒有到Do方法,我不知道我做錯了嗎?

道歉,如果這是完全錯誤的,我第一次使用的Rx :)

編輯:每下面的建議,我改變DoSubscribe,但我仍然沒有得到任何結果,如果我用Throttle 。我應該使用它嗎?

回答

10

我認爲這正在通過設計,您只需要使用Sample,它正是你想要的。!!!!

source.Sample(TimeSpan.FromSeconds(60)).Subscribe(x => /* .. */); 
+0

更好! :) – 2012-07-26 11:02:54

3

鑑於此片段,直到您訂閱Observable後纔會發生任何事情。 IIRC,只有當有人打電話給Subscribe時,纔會啓動該事件(當您處置訂閱時,它是呃,未連線)。

我儘量避免使用Do.一個observable是一個值流,你應該通過在Subscribe期間傳入的方法真正處理這些值(以及流結束或錯誤)。那麼它會成爲一種副作用 - 你在通往OnNext方法的過程中所做的價值。因爲..

的單向節流閥的工作原理是,它等待的時間給定的量的暫停

+1

是的 - 你已經做了不Foreach'ing一個LINQ語句的等效開關你做的訂閱 – 2012-07-25 22:42:52

+0

D'哦,謝謝兩位 – 2012-07-26 08:36:51

2

好油門不會解決這個問題,讓我們說你會得到一個事件每一秒,你的油門是1分鐘,你永遠不會看到任何東西。除非您的信息流發生了什麼情況,並且突然間有1分鐘以上的停頓。

Throttle最常用的例子之一就是將它用於自動完成框,在那裏你不想爲每個擊鍵啓動過濾列表的請求,所以你設置一個油門讓我們說300ms,所以當至少用戶停止輸入至少300毫秒,您將觸發搜索。

我想知道您的解決方案是否會從緩衝區或窗口中受益?我敢打賭,保羅可以找出比我的大腦現在更可怕的方法。使用的Rx多了幾個月的現在:(

7

還沒有做到這一點:

Observable.FromEventPattern(h => myThing.SomeEvent += h, h => myThing.SomeEvent -= h) 
    .Window(TimeSpan.FromSeconds(60)) 
    .SelectMany(x => x.TakeLast()) 
    .Subscribe(x => /* ... */); 
+0

優秀非常感謝 – 2012-07-26 10:17:10

+0

出於好奇,當事件發生時,這個流發出了什麼?運行時間超過60s? – Schneider 2017-01-23 07:02:55

相關問題