Rx .NET - 强制缓冲区发出

时间:2017-10-11 12:34:23

标签: c# system.reactive rx.net

我想使用Rx Buffer功能:

var source = new Subject<Price>();
var buffer = source
    .Buffer(TimeSpan.FromSeconds(30), 5)
    .Where(p => p.Any());

这意味着当缓冲区达到自上次发射后5或30秒的大小时发生(发布给订阅者)。

但我需要能够按需发出 - 例如当我收到高优先级序列项时。然后我想将它添加到observable(source.OnNext())并以某种方式强制它发出(这意味着返回缓冲区中的所有元素并清除它)。

我知道我可以添加以下代码:

var flusher = new Subject<Price>();
var closing = flusher.Select(x => new List<Price> {x});
var query = buffer.Merge(closing).Subscribe(something);

并调用flusher.OnNext(highPriorityItem),我将发出它。

但在这种情况下,我有两个独立的序列,有两个不同的发射。当缓冲区已满或特定项目按顺序出现时,我需要一个发射。

Force flush count-type Observable.Buffer c#Force flush to Observable.Buffer c#似乎不适合我

2 个答案:

答案 0 :(得分:4)

我认为decPL在这里有基本的想法,但他的解决方案并不稳定。根据{{​​1}}观察者的调度程序,即使按正确的顺序订阅,您也可能获得不可预测的结果。那是因为input有多个独立订阅。您需要通过input调用全部推送,以确保只有一个订阅。

此外,它还需要一种在处理订阅时进行清理的方法。所以它还需要通过.Publish(...)调用。

以下是:

.Create(...)

答案 1 :(得分:2)

编辑:@Enigmativity绝对正确,请参考他的回答。保持这一点完整,希望在这里确定思考过程更容易。

尝试以下内容:

var input = new Subject<Price>(); //your input observable

var flush = new Subject<long>(); //used to manually flush the 'buffer' for important prices
var timeBuffer
   = Observable.Timer(TimeSpan.FromSeconds(10)); //controls the time-based part of 'buffer'
var sizeBuffer = input.Buffer(5).Select(l => 0L); //controls the size-based part of 'buffer'

var bufferedInput = input.Window(()=>Observable.Merge(timeBuffer, sizeBuffer, flush))
                         .SelectMany(w => w.ToList())
                         .Subscribe(w => DO_SOMETHING_WITH_PRICES(w));

//Flush on important price (NOTE - order of the two subscriptions matter)
input.Where(p => p.IS_IMPORTANT).Subscribe(p => flush.OnNext(0L));