c# - 为什么 IObservables 链完全为每个订阅解析?

标签 c# system.reactive

我有一个问题,IObervables 链是如何解决的。 我认为,如果多个观察者订阅同一个 IObservable,则整个链只会在流发出新项目时解析一次。

相反,整个链似乎是为每个订阅运行的。

如果我的整个程序逻辑都是使用 IObservables 并将它们链接在一起,那么在我看来,代码运行相同的方法并产生相同的结果是不合理的。

  • 这是有意为之的行为吗?为什么?

  • 如果是这样,是否可以避免?或者这是个坏主意?

下面的代码是用 LINQPad 写的:

{
    var subject = Observable.Range(1, 1);

    var observable1 = subject
        .Select(value =>
        {
            var nextValue = value + 2;
            Console.Write("\n Result of expensive computation: " + nextValue);
            return nextValue;
        });

    var observable2 = observable1
        .Select(value =>
        {
            var nextValue = 2 * value;
            Console.Write("\n Result of another expensive computation: " + nextValue);
            return nextValue;
        });

    observable2.Subscribe(_ => Console.Write("\n Data received on first subscription."));

    observable2.Subscribe(_ => Console.Write("\n Data received on second subscription."));
}

结果:

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on first subscription.

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on second subscription.

然而我期望:

Result of expensive computation: 3

Result of another expensive computation: 6

Data received on first subscription.

Data received on second subscription.

感谢您的回答。

干杯, 罗布

最佳答案

首先回答你的问题:

  • 是的,这是预期的行为。
  • 是的,这是可以避免的。
  • 回避不是一个坏主意。

正如@supertopi 所说,您创建了一个冷可观察对象,它的功能与您概述的一样。将它变成热可观察对象,您将拥有所需的功能。

您可以按如下方式进行:

{
    var subject = Observable.Range(1, 1);

    var observable1 = subject
        .Select(value =>
        {
            var nextValue = value + 2;
            Console.Write("\n Result of expensive computation: " + nextValue);
            return nextValue;
        });

    var observable2 = observable1
        .Select(value =>
        {
            var nextValue = 2 * value;
            Console.Write("\n Result of another expensive computation: " + nextValue);
            return nextValue;
        });

    var hotObservable = observable2.Publish().RefCount();

    hotObservable.Subscribe(_ => Console.Write("\n Data received on first subscription."));

    hotObservable.Subscribe(_ => Console.Write("\n Data received on second subscription."));

}

冷 Observables:

  • 多个订阅触发链式操作的多个代码重新运行
  • 通常来自Observable.Create/Range/Generate/Interval/Timer
  • 就像可枚举的项目,项目之间有明确定义的时间间隔。

热门 Observables:

  • 多个订阅通常共享链式操作的结果
  • 通常来源于一个事件、已发布的冷观察对象或一个主题
  • 喜欢你可以处理的一系列事件;不管你喜不喜欢,它们都会发生。

在我看来,最好的区别在于源是否在没有订阅的情况下“运行”。例如,无论是否有人订阅,按钮点击事件仍然会发生。相反,Observable.Timer 在没有订阅的情况下什么都不做。

至于为什么……我不能代表 Rx 设计师。冷 vs 热 observables 是混淆/错误的常见来源。我认为围绕它们有更好的明确性可以改善这种情况。话虽如此,我不确定那是多么可行。

关于c# - 为什么 IObservables 链完全为每个订阅解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40344522/

相关文章:

c# - 如何设置 Observable 来监视属性?

c# - 使用 .NET Rx 观察随 Action 事件改变的属性

c# - 如何获取内容控件中的元素

c# - 如何将多个错误传递给 ReplaySubject?

c# - 如何将这些数据行更改提交回数据库

c# - ountputcache 属性 sqldependency mvc 中的多个表

c# - 并发流图

javascript - catch 和 onErrorResumeNext 的区别

c# - 在 Visual Studio 2008 项目中存储版本号的最佳方式是什么?

使用 COM 端口/使用 USB 串行 COM 端口与 xbee 模块通信的 C# 程序