从顶部

时间:2017-09-26 09:09:18

标签: .net system.reactive reactive-programming reactive rx.net

我想使用一个可以随时填充的IObservable。

我有这种扩展方法:

public static IObservable<TOut> Drain<TSource, TOut>(this IObservable<TSource> source,
        Func<TSource, IObservable<TOut>> selector)
{
    return Observable.Defer(() =>
    {
        BehaviorSubject<Unit> queue = new BehaviorSubject<Unit>(new Unit());

        return source
            .Zip(queue, (v, q) => v)
            .SelectMany(v => selector(v)
                .Do(_ =>
                {

                }, () =>
                {
                    queue.OnNext(new Unit());
                })
            );
    });
}

我使用如下:

_moviesToTranslateObservable = new Subject<IMovie>();
_moviesToTranslateObservable.Drain(s => Observable.Return(s).Delay(TimeSpan.FromMilliseconds(250)))
  .Subscribe(async movieToTranslate =>
      {
      }

一旦按下新项目:

_moviesToTranslateObservable.OnNext(movieToTranslate);

使用IObservable。

我的问题是,当我添加很多项目时,我想要的不是第一个添加的项目,而是最后添加的项目(如堆栈,而不是队列)。

我怎样才能做到这一点? BehaviorSubject是否适合堆栈消费行为?

1 个答案:

答案 0 :(得分:2)

我知道变量名称是queue,但BehaviorSubject实际上并不是一个队列,它更像是一个锁。排队确实发生在Zip函数内,该函数带有内部队列。

就FIFO和LIFO之间的切换而言,我不确定你想要什么标准,但这里是Drain的FIFO版本。

public static IObservable<TOut> DrainReverse<TSource, TOut>(this IObservable<TSource> source,
        Func<TSource, IObservable<TOut>> selector)
{
    return Observable.Defer(() =>
    {
        BehaviorSubject<Unit> queue = new BehaviorSubject<Unit>(new Unit());
        var stack = new Stack<TSource>();

        return source
            .Do(item => stack.Push(item))
            .Zip(queue, (v, q) => v)
            .Select(_ => stack.Pop())
            .SelectMany(v => selector(v)
                .Do(_ =>
                {

                }, () =>
                {
                    queue.OnNext(new Unit());
                })
            );
    });
}

与以下运行代码一起使用时:

var s = new Subject<int>();
var d = s.DrainReverse(i => Observable.Return(i).Delay(TimeSpan.FromMilliseconds(250)));
d.Subscribe(i => Console.WriteLine(i));
s.OnNext(0);
s.OnNext(1);
s.OnNext(2);
s.OnNext(3);
s.OnNext(4);
s.OnNext(5);

哪个正确地产生0, 5, 4, 3, 2, 1