我的应用中存在背压问题,该应用通过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 ...没有值被丢弃!