何为Reactive Extensions(Rx)

Rx是一个遵循函数式编程的类库,它引用观察者以及迭代器设计模式对可观察对象产生的数据进行异步消费。使用Rx,

开发人员将使用LINQ运算符操作异步数据流,并使用调度程序参数化异步数据流中的并发性,简单地说,Rx = Observables + LINQ + Schedulers。

使用Rx需要Nuget安装System.Reactive Nuget包

Rx的使用场景

响应式UI

UI界面上,用户对一个绑定数据集合的控件进行关键字查询。常规的流程是我们必须在等待用户键盘按下指定的完成键(如回车)或鼠标点击查询按钮后程序才开始执行相应的查询处理。但假设需求变更:“用户希望在每输入一个关键字后就能及时将关键字相应的查询结果集绑定到控件” 如果面临这个需求,那你会如何实现呢? 你会少不了定义相应的全局状态字段,少不了相应的时间间隔刷新。我相信写出来的代码也会让你很烦恼。 其实你有更好的选择,那就是我们的主角Rx。

Rx 核心

Rx有两个核心接口 IObservable<T>、IObserver<T>

IObservable<T>

先来看此接口的结构:

IObservable<T>接口就提供一个Subscribe(订阅)方法,入参是一个观察者对象接口
我们可以将IObservable<T>称之为被观察者(可观察者),IObserver<T>称之为观察者

通过可接口签名可以看出被观察者需要输出T类型的对象。需要理解被观察者IObservable<T>我们需要与现有的一些常规知识点做出比较,这里我们用IEnumerable<T>比较。
我想我们都使用过Linq,操作过IEnumerable<T>集合,IEnumerable<T>集合有个明显的状态就是它所存储的元素是静态的。集合内的元素状态除非代码显示的新增或删除、修改,否则这个集合基本是静态(数据未变动)的。但是IObservable<T>则不同,它的元素是根据被观察者提供的数据而变动的(不可预测的),就好比在UI上你无法预测用户的操作行为一样。

下面这个表格可以看出两者区别

IEnumerable

可方便的列举集合元素值

IObservable

可观察对象变动的值

IObserver<T>

IObserver<T>接口可以理解为消费被贯彻着提供数据的一个接口,它的三个方法决定了本次数据流的观察行为的走向。
通俗理解就是被观察者生成数据,观察者消费数据。

来看下IObserver<T>的结构

  • OnNext 表示消费新数据
  • OnError 表示观察数据流出现异常
  • OnCompleted 表示明确关闭观察数据流

代码示例

下面代码定义了一个可观察的队列,该队列会提供给观察者三个int类型的入参 1、2、3 供观察者对象的OnNext方法消费。 MyConsoleObserver(观察者)在得到数据后打印出来。

  class Program
{ static void Main(string[] args)
{
Test();
} private static void Test()
{
var numbers = new MySequenceOfNumbers();
var observer = new MyConsoleObserver<int>();
numbers.Subscribe(observer);
Console.ReadLine();
} } /// <summary>
/// 自定义被观察队列
/// </summary>
public class MySequenceOfNumbers : IObservable<int>
{
public IDisposable Subscribe(IObserver<int> observer)
{
observer.OnNext();
observer.OnNext();
observer.OnNext();
observer.OnCompleted();
return Disposable.Empty;
}
} /// <summary>
/// 自定义观察者对象
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyConsoleObserver<T> : IObserver<T>
{
public void OnNext(T value)
{
Console.WriteLine("接收到 value {0}", value);
}
public void OnError(Exception error)
{
Console.WriteLine("出现异常! {0}", error);
}
public void OnCompleted()
{
Console.WriteLine("关闭观察行为");
}
}

通过示例代码我们得知了Rx.Net的数据流订阅、消费流程。

Subject<T>

我们再来认识下Subject<T>,Subject是一个IObservable,它以命令形式生成一个值,并将该值推送给观察者对象。我们看下Subject<T>的结构。

看这继承关系,我们继续看SubjectBase<T>里面有些啥~

哎呀,这个类真不得了啊,把IObserver<T>和IObservable<T>都给继承了。这不是可以自己提供数据自己进行订阅和消费了么....
我们来看看Subject<T>是怎么玩的:

    private static void SubjectTest()
{
//定义一个 类型string的Subject对象
var inputs = new Subject<string>();
//订阅数据流
inputs.Subscribe((p => Console.WriteLine($"得到的值:{p}")));
//循环造数据
for (int i = ; i < ; i++)
{
inputs.OnNext($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, 下标:{i}");
}
Console.ReadLine();
}

执行结果如下图:

需要注意的是订阅方法需要在数据生成前声明。

总结

好啦,要睡觉啦,基本上Rx核心的几个点就先讲到这,我们也来总结下Rx.Net的几个核心知识点:

  • 可观察(被观察)对象生产数据;
  • 观察者总是被动接收数据;
  • 需要明确订阅后观察者才得以消费数据;

这里也只是自己的一个学习总结,Rx也不是眼前的几个小示例就可以一目了然,不过核心的知识基本上就是这些。至于还有一些操作符的话相信用过Linq的话上手不难,难点在于需要在实际业务中找到合适的场景使用,只有不断使用才会融会贯通。但是任何技术都不能滥用,每一项新技术都有它最佳使用场景,优秀的开发者需要做好权衡。

Reactive Extensions 相见恨晚的Rx.Net的更多相关文章

  1. Reactive Extensions(Rx) 学习

    Bruce Eckel(著有多部编程书籍)和Jonas Boner(Akka的缔造者和Typesafe的CTO)发表了“反应性宣言”,在其中尝试着定义什么是反应性应用. 这样的应用应该能够: 对事件做 ...

  2. 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线 ...

  3. Reactive Extensions(Rx)并发浅析

    Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...

  4. 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流

    使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...

  5. .Net并行编程 - Reactive Extensions(Rx)并发浅析

    关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...

  6. Rx (Reactive Extensions)

    The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using ...

  7. Rx (Reactive Extensions)介绍

    Reactive Extensions (Rx) 原来是由微软提出的一个综合了异步和基于事件驱动编程的库包,使用可观察序列和LINQ-style查询操作. 使用Rx, 开发者可以用Observable ...

  8. Reactive Extensions介绍

    Reactive Extensions(Rx)是对LINQ的一种扩展,他的目标是对异步的集合进行操作,也就是说,集合中的元素是异步填充的,比如说从Web或者云端获取数据然后对集合进行填充.Rx起源于M ...

  9. 2、Reactive Extensions for .NET(译)

    实验3-引入 .net 中的 events 到 Rx 目标:前面实验中的使用各种工厂构造方法创建一个 可观察序列是一个部分.把 .net 中现有的异步数据源进行关联 是更重要的事情.在这次实验中我们将 ...

随机推荐

  1. BZOJ_3144_[Hnoi2013]切糕_最小割

    BZOJ_3144_[Hnoi2013]切糕_最小割 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R ...

  2. BZOJ_3038_上帝造题的七分钟2_线段树

    BZOJ_3038_上帝造题的七分钟2_线段树 题意: XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分 ...

  3. EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下?

    前言 这个问题从未遇见过,是一位前辈问我EF Core内存泄漏问题时我才去深入探讨这个问题,刚开始我比较惊讶,居然还有这种问题,然后就有了本文,直接拿前辈的示例代码并稍加修改成就了此文,希望对在自学E ...

  4. python五种调试或排错的方法

    1.print,直接打印,比较简单而且粗暴   在代码中直接输入print+需要输出的结果,根据打印的内容判断即可   2.assert断言,很方便,测试人员常常在写自动化用例的时候用的比较多   如 ...

  5. 从壹开始 [Admin] 之四 || NetCore + SignalR 实现日志消息推送

    缘起 哈喽大家周一好呀,感觉好久没有写文章了,上周出差了一次,感觉还是比坐办公室好的多,平时在读一本书<时生>,感兴趣的可以看看

  6. vue笔记 递归组件的使用

    递归组件 什么是递归组件? 组件自身去调用组件自身. 代码示例 DetailList.vue(子组件-递归组件) <template> <div> <div class= ...

  7. 基本服务器的AAA实验

    一.实验拓扑 二.网络地址分配 三.不同网段互相PING通 PC-A ping PC-B PC-A ping PC-C PC-B ping PC-C 四.配置过程 (1)在路由器R1上配置本地用户账号 ...

  8. Java8新特性之二:方法引用

    上一节介绍了Java8新特性中的Lambda表达式,本小节继续讲解Java8的新特性之二:方法引用.方法引用其实也离不开Lambda表达式. 1.方法引用的使用场景 我们用Lambda表达式来实现匿名 ...

  9. 使用 ASP.NET Core MVC 创建 Web API(五)

    使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 使用 ASP.NET Core MVC 创建 Web API(二) 使 ...

  10. 简单计算器 安卓 Android 作业

    Android老师布置的课程作业——简单计算器 功能要求实现四则运算,参考界面见下图: 首先给各位老铁提供apk安装包以及项目压缩包,略表诚意~ github地址:https://github.com ...