我假設你想要的以下行爲:
- 初始事件發生後,緩衝所有事件在接下來的10秒。
- 一旦這個10秒的窗口關閉,下一個應該在10秒後爲所有事件觸發一個新的10秒緩衝區。
所以我們假設我們有5個事件在5秒內均勻分佈,13秒間隔,然後在5秒內均勻分佈另外5個事件。大理石圖是這樣的:
timeline: 0--1--2--3--4--5--6--7--8--9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27
events : x--x--x--x--x-------------------------------------x--x--x--x--x------------------
stdbuff : |----------------------------|-----------------------------|---------------------
desired : BeginCapture-----------------Return---------------BeginCapture------------------Return
使用直線前進Buffer
的是,它看起來像上面譜寫的stdbuff
,而分手事件的第二組分爲兩組,造成兩人列出了問題第二組活動:一個有三個活動,一個有兩個活動。您需要一個列表(針對第二組),使用類似desired
流的邏輯。開始在0捕獲,返回列表在10.開始在17捕獲,在27返回列表。
如果我誤解了你(再次),請張貼大理石圖表,類似於上面,代表你想要如何事情要工作。
假設我理解你正確,下面的代碼將工作...
//var initialSource = Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Created))
// .Merge(Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Changed)));
//Comment this out, and use the above lines for your code. This just makes testing the Rx components much easier.
var initialSource = Observable.Interval(TimeSpan.FromSeconds(1)).Take(5)
.Concat(Observable.Empty<long>().Delay(TimeSpan.FromSeconds(13)))
.Concat(Observable.Interval(TimeSpan.FromSeconds(1)).Take(5));
initialSource
.Publish(_source => _source
.Buffer(_source
.Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
.DistinctUntilChanged()
.Delay(TimeSpan.FromSeconds(10))
)
)
.Subscribe(list =>
{
Debug.WriteLine($"Time-stamp: {DateTime.Now.ToLongTimeString()}");
Debug.WriteLine($"List Count: {list.Count}");
});
說明:
首先,我們需要確定 '主要事件',那些代表BeginCapture
上面的desired
流描述中的註釋。可以發現這樣的:
var primaryEvents = initialSource
.Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
.DistinctUntilChanged();
一旦我們有了BeginCapture
事件,它可以表示一個窗口開放,這是很容易找到Return
事件,或閉窗:
var closeEvents = primaryEvents.Delay(TimeSpan.FromSeconds(10));
在實踐中,因爲沒有密切和開放的,我們關心之間發生的,我們只需要擔心關閉事件,所以我們可以把它收縮到這一點:
var closeEvents = initialSource
.Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
.DistinctUntilChanged()
.Delay(TimeSpan.FromSeconds(10));
把它插入到Buffer
與closeEvents
作爲bufferBoundaries
:
var bufferredLists = initialSource
.Buffer(initialsource
.Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
.DistinctUntilChanged()
.Delay(TimeSpan.FromSeconds(10))
);
最後,因爲我們有多個訂閱initialSource
,我們需要使用Publish
確保併發正常工作,導致最終的答案。
你目前的代碼有什麼問題?你爲什麼不使用'list'?或者你想單獨處理列表中的每個項目? –
你只想讓它觸發一次或什麼?這聽起來像你的解決方案是適當的。 – Shlomo
在旁註中:您應該保留對訂閱的引用,並在您不再對這些事件感興趣時進行處置。如果您不處理訂閱並且超出範圍,那麼它可能仍然對該事件保持強烈的引用(並且可能導致泄漏)。 –