[英]Hot/Cold Observable, multiply subscribers
如何将MainEngine
Observable转换为Cold? 从这个例子:
public IObservable<int> MainEngine
{
get
{
Random rnd = new Random();
int maxValue = rnd.Next(20);
System.Diagnostics.Trace.TraceInformation("Max value is: " + maxValue.ToString());
return (from sinlgeInt in Enumerable.Range(0, maxValue)
select sinlgeInt).ToObservable();
}
}
public void Main()
{
// 1
MainEngine.Subscribe(
onNext: (item) => { System.Diagnostics.Trace.TraceInformation("Value is: " + item.ToString()); }
);
// 2
MainEngine.Subscribe(
onNext: (item) => { System.Diagnostics.Trace.TraceInformation("Gonna put it into XML: " + item.ToString()); }
);
}
问题1:在订户1和订户2上,我得到了不同的结果,但我希望他们都得到相同的结果。
问题2:从我添加第二个订户的时间点开始,它们都会继续收到相同的结果。
你的观察结果已经很冷了 。 如果您在每次订阅时都使用了observable的实例,那么您将得到相同的值。
它看起来很热的唯一方法是,如果你多次调用MainEngine
你会得到不同的可观察实例。 但这并不能使它们真正变热 。
实际上,您已经创建了一个冷的可观察工厂 。
要使MainEngine
方法真正变热,您需要添加一个Defer
调用,如下所示:
public IObservable<int> MainEngine
{
get
{
return Observable.Defer(() =>
{
Random rnd = new Random();
int maxValue = rnd.Next(20);
System.Diagnostics.Trace.TraceInformation(
"Max value is: " + maxValue.ToString());
return Observable.Range(0, maxValue);
});
}
}
另请注意,我将Enumerable.Range
更改为Observable.Range
并删除了对.ToObservable()
的调用。
为了现在真的让它变得热,这里该怎么做:
var hotObservable = MainEngine.Publish().RefCount();
这实际上意味着当您同时订阅多个observable时,它们将共享基础observable。 当没有订阅时,底层的observable就会消失,只有在新的观察者订阅时才会创建。
请记住,您的MainEngine
实现默认使用Scheduler.Immediate
运行,因此在将observable更改为在其他线程上运行之前,您将看不到此代码的好处。
我希望这有帮助。
关于你的第一个问题,问题是观察者没有订阅相同的IObservable
因为你两次调用getter。
将IObservable
分配给局部变量似乎可以解决问题:
IObservable<int> mainEngine = MainEngine;
mainEngine.Subscribe(onNext: (item) => { /* ... */ });
mainEngine.Subscribe(onNext: (item) => { /* ... */ });
关于第二个问题,如果要将订阅共享到单个IObservable
,可以使用Publish
方法:
IConnectableObservable<int> published = MainEngine.Publish();
published.Subscribe(onNext: (item) => { Console.WriteLine(item + " on observer 1"); });
published.Subscribe(onNext: (item) => { Console.WriteLine(item + " on observer 2"); });
published.Connect();
然后,两个订阅者将以交错的方式查看IObservable
的结果:
0 on observer 1
0 on observer 2
1 on observer 1
1 on observer 2
etc.
您也可以在调用Subscribe之后订阅新的观察者,之后所有订阅者都将看到相同的事件。 您可以通过在新线程上运行您的observable并引入延迟来修改您的示例来测试它:
public static void Main()
{
Random rnd = new Random();
int maxValue = rnd.Next(20);
/* Zip with Observable.Interval to introduce a delay */
IObservable<int> mainEngine = Observable.Range(0, maxValue, Scheduler.NewThread)
.Zip(Observable.Interval(TimeSpan.FromMilliseconds(100)), (a, b) => a);
/* Publish the observable to share a subscription between observers */
IConnectableObservable<int> published = mainEngine.Publish();
/* Subscribe the first observer immediately, events are not yet being observed */
published.Subscribe(onNext: (item) => { Console.WriteLine(item + " on observer 1"); });
/* Start pushing events to the first observer */
published.Connect();
/* Wait one second and then subscribe the second observer */
Thread.Sleep(1000);
published.Subscribe(onNext: (item) => { Console.WriteLine(item + " on observer 2"); });
Console.ReadKey();
}
您将仅在第一个观察者身上看到一秒钟的事件,然后两个观察者将同时看到每个事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.