异步/等待和响应式扩展(Rx)范式之间区别的代码示例?

20

System.Reactive extension for .NET新的C# 5.0(.NET 4.5) async/await都追求(或基于)future and promises constructs范式(方法)。

能否给出最简单的C#代码示例,说明它们之间的区别?

是否可以在没有I/O、Internet或数据库连接的情况下实现?

更新:
如果这个问题看起来已经回答了,请让我重新表述一下。
在使用本机.NET Iobservable/IObserver+await/async的同时,为什么要添加并开始使用Reactive(Rx)扩展.NET?

有哪些可能的例子是在没有Rx的情况下,使用本机.NET Iobservable/IObserver + await/async方法实现相同操作更笨拙或不那么高效的呢?


你有没有尝试过谷歌搜索?看起来你并没有这么做。 - fredrik
1
@fredrik,我该如何证明它没有谷歌SERP结果? - Gennady Vanin Геннадий Ванин
1
只需说出您搜索的内容并说明没有任何结果,这将向我展示您至少尝试过。 - fredrik
最接近的结果说明了为什么要在 Rx 中使用 await/async。但这并没有回答为什么在第一次使用 async/await 后还要使用 Rx。 - Gennady Vanin Геннадий Ванин
你不应该在没有 Rx 的情况下使用本地的 .NET IObservable/IObserver - Stephen Cleary
3个回答

21
未来/承诺范式通常用于返回未来的单个值。可能需要进行一些繁重的计算或IO,因此不能保证及时地同步返回。
Rx(以及代理IObserver<T>/IObservable<T>接口)是可观察序列的范例。就像同步方法可以返回单个值(int),它也可以返回一个带有一个值的IEnumerable<int>。将其与异步世界进行比较,Task<int>可以返回单个int值,IObservable<int>可以返回仅具有一个int值的序列。
因此,如果您想要使用Task<T>返回一系列值,则必须创建某种继续项,或者将值的集合/数组/列表作为T返回,例如Task<int[]>。但是,这意味着您会获得所有值或不会获得任何值。 Task/Task<T>也是具体类型,而Rx使用接口来使您从实现中抽象出来。我发现这对于单元测试很有帮助。TaskCompletionSource<T>可以帮助避免在使用任务进行测试时出现隐式并发。
最后,除了Rx正在处理值的序列(而不是单个值)这一主要区别外,Rx还设计为与LINQ一起工作,以提供查询和组合优势,这似乎在序列(静态的IEnumerable<T>或动态的IObservable<T>)中非常有效。
最终,这些是用于略微不同工作的不同工具。存在一些重叠,因此有时可以使用其中一个来执行另一个更擅长的任务。具体而言,我认为Task更适合将异步工作单元组合在一起(先做这个,然后做那个,然后做这个),而Rx更适合将事件序列组合在一起(当发生此事件时,使用来自此其他事件的数据进行操作)。

你不需要使用 Task<T[]> 来处理多个值,你可以使用 Task<IEnumerable<T>>,同时也可以使用 INotifyCollectionChanged 接口。 - Akash Kava
正如所指出的"..返回一个值的集合/数组/列表..". 这个讨论并不是关于事件(更接近于 RX),而是关于 RxTask 的比较。添加事件、APM、线程、回调以及其他异步风格将导致非常庞大的讨论,甚至可以写一本书。;-) - Lee Campbell
当这个事件发生时,使用来自另一个事件的数据执行这个动作,这个思想真的让我深感启示。最近,我尝试在React中使用hooks实现这个功能,但无法在没有顺序代码的情况下弄清楚如何做到这一点,我想我应该看看RxJs。 - marcos.borunda

5

1
另外需要注意的是,它们可以很好地配合使用:Task<T>.ToObservable() 创建了一个 IObservable<T>,最多只会产生一个结果,而 await myObservable 则允许您异步等待可观察对象的最后一个元素。 - Stephen Cleary
@StephenCleary,你可以把同样的(或不同的)内容回答一下吗? - Gennady Vanin Геннадий Ванин

5
我喜欢Reactive文档中的表格:http://reactivex.io/intro.html 我有自己的想法,将其加了第三个维度:非可组合/可组合。
不可组合:
| 单个项 | 多个项 ------|--------|-------- 同步 | 函数 | 可迭代对象 异步 | 异步函数 | Observable 可组合:
| 单个项 | 多个项 ------|----------------|------------------- 同步 | 高阶函数 | Linq/Ramda/java.util.stream 异步 | Future/promise | Rx observable 请注意,根据实现方式,你可以拥有既可以同步也可以异步操作的future和rx observables,具体取决于你要使用它们进行的操作是同步还是异步。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接