订阅异步方法时,如何仅使用ObserveLatestOn获取最新的可观察值?

时间:2019-06-04 17:32:50

标签: c# async-await reactive-programming system.reactive rx.net

我的应用中存在背压问题,该应用通过RX观测对象接收缓存项的更新,并使用长时间运行的异步方法对其进行处理。我想批处理更新并调用Task.WhenAll()并发处理批处理,直到完成。然后,我想删除这段时间内收到的所有更新,并继续处理仅包含收到的最新更新的下一批。

我正在努力使用this post中的ObserveLatestOn方法和异步订阅(即Task.Delay()以模拟长时间运行的调用)来获得简化(即无缓冲)版本的工作。

请有人能解释我在做什么或如何做到这一点? (最好是使用RX,但其他基于任务/队列的解决方案也可以)

    public async Task Test()
    {
        ConcurrentQueue<string> messageQueue = new ConcurrentQueue<string>();

        var testSub = Observable.Interval(TimeSpan.FromMilliseconds(250))
        .Do(x => messageQueue.Enqueue("source: " + x))
        .ObserveLatestOn()
        .Subscribe(i => 
        { 
            messageQueue.Enqueue($"[{i}]");
            Thread.Sleep(TimeSpan.FromSeconds(1));
        });

        // wait for test to finish
        await Task.Delay(TimeSpan.FromSeconds(4));
        testSub.Dispose();
        Console.WriteLine(string.Join(Environment.NewLine, messageQueue));          
    }

例如,上面使用Thread.Sleep()进行的非异步测试将产生预期的输出,并且订阅下降,并且只看到0、4、8 ...

  

源:0 [0]源:1源:2源:3源:4 [4]源:5源:6 ...

但是当我尝试将Task.Delay与来自here的SubscribeAsync一起使用时:

        var testSub = Observable.Interval(TimeSpan.FromMilliseconds(250))
            .Do(x => messageQueue.Enqueue("source: " + x))
            .ObserveLatestOn()
            .SubscribeAsync(async i =>
            {
                messageQueue.Enqueue($"[{i}]");
                await Task.Delay(TimeSpan.FromSeconds(1));
            });

        public static IDisposable SubscribeAsync<T>(this IObservable<T> source, Func<T, Task> onNextAsync)
        {
            return source.Select(number => Observable.FromAsync(async ct => await onNextAsync(number))).Concat().Subscribe();
        }

输出为:

  

源:0 [0]源:1源:2源:3源:4 [1]源:5源:6   来源:7来源:8 [2] ...

订阅的值变为0,1,2 ...没有值被丢弃!

0 个答案:

没有答案