我有一个问题,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/