RX: How to process n buffered items from a sequence then wait t seconds before processing the next n items?

僤鯓⒐⒋嵵緔 提交于 2019-12-06 04:35:06
// Instantiate this once, we'll use it in a closure multiple times.
var delay = Observable.Empty<int>().Delay(TimeSpan.FromMilliseconds(10));

// start with a source of individual items to be worked.
Observable.Range(0, 100000)
    // Create batches of work.
    .Buffer(20)
    // Select an observable for the batch of work, and concat a delay.
    .Select(batch => batch.ToObservable().Concat(delay))
    // Concat those together and form a "process, delay, repeat" observable.
    .Concat()
    // Subscribe!
    .Subscribe(Console.WriteLine);

// Make sure we wait for our work to be done.
// There are other ways to sync up, like async / await.
Console.ReadLine();

Alternatively, you could also sync up using async/await:

static IObservable<int> delay = Observable.Empty<int>().Delay(TimeSpan.FromMilliseconds(100));

static async Task Run()
{
    await Observable.Range(0, 1000)
        .Buffer(20)
        .Select(batch => batch.ToObservable().Concat(delay))
        .Concat()
        .Do(Console.WriteLine)
        .LastOrDefaultAsync();
}

Isn't that delay observable a nifty trick? It works because OnCompleted is delayed just like OnNext!

Building on Christopher's answer if you don't want the list elements flattened out you could do:

var delay = Observable.Empty<IList<int>>().Delay(TimeSpan.FromSeconds(10));

var query = Observable.Range(0, 100000)
                      .Buffer(20)
                      .Select(batch => Observable.Return(batch).Concat(delay))
                      .Concat();

query.Subscribe(list =>
                    {
                        Console.WriteLine(DateTime.Now);

                        foreach (var value in list)
                        {
                            Console.WriteLine(value);
                        }
                    });
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!