简体   繁体   English

RX术语:频繁观察到通知时,RX运算符中的异步处理

[英]RX terminolgy: Async processing in RX operator when there are frequent observable notifications

The purpose is to do some async work on a scarce resource in a RX operator, Select for example. 目的是在RX运算符中对稀缺资源进行一些异步工作,例如Select。 Issues arise when observable notifications came at a rate that is faster than the time it takes for the async operation to complete. 当可观察到的通知以比异步操作完成所需的时间更快的速率出现时,就会出现问题。

Now I actually solved the problem. 现在,我实际上解决了问题。 My question would be what is the correct terminology for this particular kind of issue? 我的问题是这种特殊问题的正确术语是什么? Does it have a name? 它有名字吗? Is it backpressure? 是背压吗? Research I did until now indicate that this is some kind of a pressure problem, but not necessarily backpressure from my understanding. 到目前为止,我所做的研究表明这是一个压力问题,但从我的理解来看并不一定是背压。 The most relevant resources I found are these: https://github.com/ReactiveX/RxJava/wiki/Backpressure-(2.0) http://reactivex.io/documentation/operators/backpressure.html 我发现的最相关的资源是: https : //github.com/ReactiveX/RxJava/wiki/Backpressure-(2.0) http://reactivex.io/documentation/operators/backpressure.html

Now to the actual code. 现在到实际代码。 Suppose there is a scarce resource and it's consumer. 假设有一种稀缺资源,它是消费者。 In this case exception is thrown when resource is in use. 在这种情况下,使用资源时会引发异常。 Please note that this code should not be changed. 请注意,此代码不应更改。

public class ScarceResource
{
    private static bool inUse = false;

    public async Task<int> AccessResource()
    {
        if (inUse) throw new Exception("Resource is alredy in use");

        var result = await Task.Run(() =>
        {
            inUse = true;
            Random random = new Random();
            Thread.Sleep(random.Next(1, 2) * 1000);
            inUse = false;

            return random.Next(1, 10);
        });

        return result;
    }
}

public class ResourceConsumer
{
    public IObservable<int> DoWork()
    {
        var resource = new ScarceResource();
        return resource.AccessResource().ToObservable();
    }
}

Now here is the problem with a naive implementation to consume the resource. 现在这是天真的实现要消耗资源的问题。 Error is thrown because notifications came at a faster rate than the consumer takes to run. 引发错误是因为通知的发出速度比使用者运行速度要快。

private static void RunIntoIssue()
{
    var numbers = Enumerable.Range(1, 10);
    var observableSequence = numbers
        .ToObservable()
        .SelectMany(n =>
        {
            Console.WriteLine("In observable: {0}", n);
            var resourceConsumer = new ResourceConsumer();
            return resourceConsumer.DoWork();
        });

    observableSequence.Subscribe(n => Console.WriteLine("In observer: {0}", n));
}

With the following code the problem is solved. 使用以下代码可以解决问题。 I slow down processing by using a completed BehaviorSubject in conjunction with the Zip operator. 我通过结合使用完整的BehaviorSubject和Zip运算符来减慢处理速度。 Essentially what this code does is to take a sequential approach instead of a parallel one. 从本质上讲,这段代码所做的是采用顺序方法,而不是并行方法。

private static void RunWithZip()
{
    var completed = new BehaviorSubject<bool>(true);
    var numbers = Enumerable.Range(1, 10);
    var observableSequence = numbers
        .ToObservable()
        .Zip(completed, (n, c) =>
        {
            Console.WriteLine("In observable: {0}, completed: {1}", n, c);
            var resourceConsumer = new ResourceConsumer();
            return resourceConsumer.DoWork();
        })
        .Switch()
        .Select(n =>
        {
            completed.OnNext(true);
            return n;
        });

    observableSequence.Subscribe(n => Console.WriteLine("In observer: {0}", n));
    Console.Read();
}

Question Is this backpressure, and if not does it have another terminology associated? 问题这是背压吗?如果不是,是否还有其他术语相关联?

You're basically implementing a form of locking, or a mutex. 您基本上是在实现一种锁定形式,即互斥体。 Your code an cause backpressure, it's not really handling it. 您的代码造成了背压,实际上并没有解决它。

Imagine if your source wasn't a generator function, but rather a series of data pushes. 想象一下,如果您的源代码不是生成器函数,而是一系列数据推送。 The data pushes arrive at a constant rate of every millisecond. 数据推送以每毫秒恒定的速率到达。 It takes you 10 Millis to process each one, and your code forces serial processing. 处理每一个需要10 Millis,您的代码将强制进行串行处理。 This causes backpressure: Zip will queue up the unprocessed datapushes infinitely until you run out of memory. 这会导致背压:Zip将无限处理未处理的数据推送,直到耗尽内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM