Mar*_*arl 6 c# system.reactive
我是Rx的新手.我可以看到使用Hot Observables的一些真正的好处,但是我最近被问到一个关于冷可观察和等效可枚举之间的区别的问题(参见下面的代码片段)...
var resRx = Observable.Range(1, 10);
var resOb = Enumerable.Range(1, 10);
Run Code Online (Sandbox Code Playgroud)
任何人都可以非常简单地解释两者之间的区别是什么,以及从冷可观察者到可枚举者可以得到什么好处.
Gid*_*rth 15
两者之间存在一些差异.
谁控制'枚举'
对于可观察(热或冷),可观察的是确定何时以及在什么线程上返回值.另一方面,可枚举在您请求时获取每个值,并在请求枚举的线程上处理.
代码流程
处理枚举通常在每个循环中完成(或偶尔获取枚举数并使用while循环).您的代码通常会在继续之前处理所有值.Observable需要回调.阻止进一步执行代码(比如不要退出控制台应用程序)需要额外的代码.对于可观察对象有一些阻塞运算符,例如First,但它们是例外而不是正常使用的规则.
以这个简单的示例程序为例.使用可枚举的值,所有值都会在继续下一部分之前编写.但是,不能保证可以观察到可观察值.在程序终止之前写入多少个值几乎就是竞争条件.
static void Main(string[] args)
{
var xs = Enumerable.Range(1, 10);
foreach (var x in xs)
{
Console.WriteLine(x);
}
//at this point, all values have been written
var ys = Observable.Range(1, 10);
ys.Subscribe(y => Console.WriteLine(y));
//at this point, no values have been written (in general)
//either add a Console.ReadKey or some sort of wait handle that
//is set in the OnCompleted of the observer to get values
}
Run Code Online (Sandbox Code Playgroud)
异步进程
就像你必须编写额外的代码来阻止和等待一个observable一样,编写一个使用异步进程的IEnumerable需要一些额外的工作.这是两者之间真正发挥作用的地方.
例如,在我目前正在处理的应用程序中,我需要搜索可能连接到串行端口的设备.IObservable非常适合这种情况,因为它允许我进行回调并在我找到它时通知应用程序,而不必阻塞和操作完成.这个observable有资格作为cold observable,因为除非有订阅者,否则它不会推送数据,并且每个订阅都会获得所有结果.(与典型的冷观察不同,我在订阅之前开始工作,但没有数据丢失,因为它被缓冲到重放主题中.)但是,由于异步,将它转换为Enumerable对我来说没有多大意义.性质.
你习惯使用的几乎所有Enumerables都是"冷"枚举?为什么?因为如果你在Enumerable.Range上两次使用ForEach,那么你得到2倍的数字.
如果Enumerable.Range是Hot Enumerable,它只会给你一次列表而第二个ForEach只是空的.
对于Rx,Cold Observable意味着每次调用Subscribe(相当于Rx中的ForEach)时,您都会收到一个新的东西列表.像FromEvent这样的Hot Observable不会在每次订阅时为您提供新的事件流,它只是与同一事件流的另一个连接.
这里Rx有什么优势?能够将该范围转换为异步请求:
IObservable<Image> fetchImageByIndex(int imageIndexOnSite);
Observable.Range(0, 10)
.SelectMany(x => fetchImageByIndex(x))
.Subscribe(image => saveImageToDisk(image));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1022 次 |
| 最近记录: |