Reactive Extensions 相见恨晚的Rx.Net
何为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的更多相关文章
- Reactive Extensions(Rx) 学习
Bruce Eckel(著有多部编程书籍)和Jonas Boner(Akka的缔造者和Typesafe的CTO)发表了“反应性宣言”,在其中尝试着定义什么是反应性应用. 这样的应用应该能够: 对事件做 ...
- 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
我之前有一篇文章介绍到了Reactive Extension这个组件,请参考下面的文章,其中有一些基本的概念和相关的链接 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线 ...
- Reactive Extensions(Rx)并发浅析
Reactive Extensions(Rx)并发浅析 iSun Design & Code .Net并行编程 - Reactive Extensions(Rx)并发浅析 关于Reactive ...
- 使用Reactive Extensions(Rx),对短时间内多次发生的事件限流
使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 牛刀小试:使用Reactive Extensions(Rx),对短时间内多次发生的事件限流 我之前有一篇文章介绍到了R ...
- .Net并行编程 - Reactive Extensions(Rx)并发浅析
关于Reactive Extensions(Rx) 关于Reactive Extensions(Rx),先来看一下来自微软的官方描述: The Reactive Extensions (Rx) is ...
- Rx (Reactive Extensions)
The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using ...
- Rx (Reactive Extensions)介绍
Reactive Extensions (Rx) 原来是由微软提出的一个综合了异步和基于事件驱动编程的库包,使用可观察序列和LINQ-style查询操作. 使用Rx, 开发者可以用Observable ...
- Reactive Extensions介绍
Reactive Extensions(Rx)是对LINQ的一种扩展,他的目标是对异步的集合进行操作,也就是说,集合中的元素是异步填充的,比如说从Web或者云端获取数据然后对集合进行填充.Rx起源于M ...
- 2、Reactive Extensions for .NET(译)
实验3-引入 .net 中的 events 到 Rx 目标:前面实验中的使用各种工厂构造方法创建一个 可观察序列是一个部分.把 .net 中现有的异步数据源进行关联 是更重要的事情.在这次实验中我们将 ...
随机推荐
- 用Service+Broadcast解决倒计时过程中Activity被销毁的问题
主要思想是这样的:将倒计时CountDownTimer放在Service里面进行,每过一秒就一条发广播,在主Activity里注册广播,收到广播后更新UI. 一.写一个类CodeTimerServic ...
- 【SQL】面面俱到 | 在SQL中使用CUBE和ROLLUP实现数据多维汇总
偶然在网上看到一篇文章,讲到数据汇总,提到了CUBE,感觉有些晦涩,想试着自己表述一下.同时,个人也认为CUBE还是很有用的,对SQL或数据分析感兴趣的小伙伴不妨了解一下,或许有用呢! 先设定个需求, ...
- FreeSql 新的八大骚功能,.NETCore 你必须晓得的 ORM
前言 FreeSql 目前版本号 0.5.5,预计明年元旦发布 1.0.0,切莫小看了版本号,目前单元测试方法1350+,并且每个方法内的涵盖面又比较广(不信的话见下图),每一次版本发布都作了较多的测 ...
- 【原】js数组对象去重最简单的方法
简单的数组去重是比较简单的,方法也特别多,如给下面的数组去重: let arr = [1,2,2,4,9,6,7,5,2,3,5,6,5] 最常用的可以用for循环套for循环,再用splice删除重 ...
- frida的用法--Hook Java代码篇
frida是一款方便并且易用的跨平台Hook工具,使用它不仅可以Hook Java写的应用程序,而且还可以Hook原生的应用程序. 1. 准备 frida分客户端环境和服务端环境.在客户端我们可以编写 ...
- SpaceSyntax【空间句法】之DepthMapX学习:第二篇 输出了什么东西 与 核心概念
这节比较枯燥,都是原理,不过也有干货.这篇能不能听懂,就决定是否入门...所以,加油吧 博客园/B站/知乎/CSDN @秋意正寒 转载请在文头注明本文地址 本篇讲空间句法的几个核心概念,有一些也是重 ...
- API做翻页的两种思路
在开发API的时候,有时候数据太多了,就需要分页读取. 基于偏移量的分页(Offset-based) 这种方式就是会提供一个每页笔数(page size)来定义返回条目的最大数,提供一个页数(page ...
- C# Memory Cache 踩坑记录
背景 前些天公司服务器数据库访问量偏高,运维人员收到告警推送,安排我团队小伙伴排查原因. 我们发现原来系统定期会跑一个回归测试,该测运行的任务较多,每处理一条任务都会到数据库中取相关数据,高速地回归测 ...
- Hibernate内容详解
一:引入Hibernate的jar包 http://t.cn/EioD1xk 二:配置Hibernate的核心配置文件hibernate.cfg.xml <!DOCTYPE hibernate- ...
- spring boot redis 数据库缓存用法
缓存处理方式应该是 1.先从缓存中拿数据,如果有,直接返回.2.如果拿到的为空,则数据库查询,然后将查询结果存到缓存中.由此实现方式应该如下: private String baseKey = &qu ...