强制刷新计数类型可观察。缓冲区c#

强制刷新计数类型可观察。缓冲区c#,c#,buffer,system.reactive,C#,Buffer,System.reactive,基于这个讨论刷新基于时间的缓冲区的问题: ,我很难理解如何将这里给出的答案转换为我按计数而不是按时间缓冲的情况: var subject = new Subject<Unit>(); var closing = Observable .Timer(new TimeSpan(0, 0, 1, 30)) .Select(x => Unit.Default); var query = mFluxObservable .Buffer(() =&

基于这个讨论刷新基于时间的缓冲区的问题: ,我很难理解如何将这里给出的答案转换为我按计数而不是按时间缓冲的情况:

var subject = new Subject<Unit>();
var closing = Observable
    .Timer(new TimeSpan(0, 0, 1, 30))
    .Select(x => Unit.Default);

var query =
    mFluxObservable
        .Buffer(() => Observable
            .Amb(subject, closing)
            .Take(1));
我的消息来源是“热”,如果这有帮助的话


PS:我可以使用
可观察对象来解决问题。创建
和某种内部计数器,但不能不锁定…

我认为您可以通过使用关闭可观察对象中的源并将其与刷新可观察对象合并来完成。以下几点对我很有用:

 var source = new Subject<Unit>();
 var flush = new Subject<Unit>();

 // close buffer every 3 values or when a flush value arrives
 var closing = source.Buffer(3) 
            .Select(x => Unit.Default)
            .Merge(flush);

 var query = source.Buffer(() => closing)
         .Subscribe(Console.WriteLine);

// some test values
source.OnNext(Unit.Default);
source.OnNext(Unit.Default);
source.OnNext(Unit.Default);
source.OnNext(Unit.Default);

// flush buffer
flush.OnNext(Unit.Default);
var source=新主题();
var flush=新主题();
//每3个值或当刷新值到达时关闭缓冲区
var closing=source.Buffer(3)
.Select(x=>Unit.Default)
.合并(齐平);
var query=source.Buffer(()=>关闭)
.Subscribe(Console.WriteLine);
//一些测试值
source.OnNext(单位默认值);
source.OnNext(单位默认值);
source.OnNext(单位默认值);
source.OnNext(单位默认值);
//刷新缓冲区
flush.OnNext(单位默认值);

到目前为止,我得到的是:

var flush = new Subject<Unit>();
var source = Observable.Interval(TimeSpan.FromSeconds(1))
            .Select(_ => Unit.Default).Publish().RefCount();
var closer = CloseGenerator(source, flush, 5);
source.Buffer(closer)

//...

private IObservable<Unit> CloseGenerator<T>(IObservable<T> source, 
                                             IObservable<Unit> flusher, int count)
{
     return Observable.CombineLatest(
                        source.Select((_, i) => i), 
                        flusher.Select((_, i) => i).StartWith(-1))
             .Select(ar => Tuple.Create(ar[0], ar[1]))
             .Scan(Tuple.Create(-1, -1), (prev, next) =>
                 {
                     if(next.Item2 != prev.Item2 || next.Item1 == prev.Item1 + count)
                         return next;
                     else
                         return prev;
                 }
             )
             .DistinctUntilChanged().Skip(1) //This is 'DistinctExceptFirst'
             .Select(_ => Unit.Default);
}
var flush=新主题();
var source=可观测的时间间隔(时间跨度从秒(1))开始)
.Select(=>Unit.Default).Publish().RefCount();
var closer=闭合发电机(电源,冲洗,5);
source.Buffer(更接近)
//...
专用IObservable CloseGenerator(IObservable震源,
IObservable冲洗器,int计数)
{
返回可观测的(
来源。选择((_,i)=>i),
flusher.Select((i,i)=>i.StartWith(-1))
.Select(ar=>Tuple.Create(ar[0],ar[1]))
.Scan(Tuple.Create(-1,-1),(上一个,下一个)=>
{
if(next.Item2!=prev.Item2 | | next.Item1==prev.Item1+count)
下一步返回;
其他的
返回上一个;
}
)
.DistinctUntilChanged().Skip(1)//这是'DistinctExceptFirst'
.Select(=>Unit.Default);
}

我认为可观察的
没有问题。创建
解决方案。在这种情况下,我认为这个扩展应该有效

public static IObservable<IList<T>> BufferExceptOnFlush<T>(this IObservable<T> source,IObservable<Unit> flusher, int bufferSize)
{
 return Observable.Create<IList<T>>(observer =>
 {
     var shared = source.Publish();
     var closing = shared.Buffer(bufferSize).Select(x => Unit.Default);
     var query = shared.Buffer(() => flusher.Amb(closing).Take(1)).SubscribeSafe(observer);
     return new CompositeDisposable(query, shared.Connect());
 });

它既适用于热观测,也适用于冷观测,因为没有双重订阅

谢谢,我马上就去试试。为了好玩,我发布了我目前的最佳近似值…Gngng,和Rx一样,解决方案非常简单,一旦其他人计算出来:)刚刚看到Ned的答案,这就解决了
public static IObservable<IList<T>> BufferExceptOnFlush<T>(this IObservable<T> source,IObservable<Unit> flusher, int bufferSize)
{
 return Observable.Create<IList<T>>(observer =>
 {
     var shared = source.Publish();
     var closing = shared.Buffer(bufferSize).Select(x => Unit.Default);
     var query = shared.Buffer(() => flusher.Amb(closing).Take(1)).SubscribeSafe(observer);
     return new CompositeDisposable(query, shared.Connect());
 });
var query = myFluxObservable.BufferExceptOnFlush(myFlusher, 5);