Reactive Extensions(Rx)并发浅析

iSun

Design & Code

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

关于Reactive Extensions(Rx)

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

The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Using Rx, developers represent asynchronous data streams with Observablesquery asynchronous data streams using LINQ operators, and parameterize the concurrency in the asynchronous data streams using Schedulers. Simply put, Rx = Observables + LINQ + Schedulers.

“Reactive Extensions(Rx)是一个类库,它集成了异步、基于可观察(observable)序列的事件驱动编程和LINQ-style的查询操作。使用Rx,开发人员可以用observable对象描述异步数据流,使用LINQ操作符异步查询数据和使用Schedulers控制异步过程中的并发。简而言之,Rx = Observables + LINQ + Schedulers。”

Reactive Extensions(Rx)就一定是多线程?

在以上的描述中,反复出现了一个词“异步”。一般来讲,提到“异步”,首先反应到的就是多线程。那问题来了,使用Reactive Extensions就一定意味着多线程吗?先来看一个示例,代码来了:

 1 static void Main(string[] args)
2 {
3 Console.WriteLine("Starting on threadId:{0}", Thread.CurrentThread.ManagedThreadId);
4 var sub = new Subject<Object>();
5
6 sub.Subscribe(o => Console.WriteLine("Received {1} on threadId:{0}", //为Observable订阅处理器(handler),输出handler thread id
7 Thread.CurrentThread.ManagedThreadId,
8 o));
9 ParameterizedThreadStart notify = obj => //委托定义,其内输出被观察对象的thread id
10 {
11 Console.WriteLine("OnNext({1}) on threadId:{0}",
12 Thread.CurrentThread.ManagedThreadId,
13 obj);
14 sub.OnNext(obj);
15 };
16 notify(1);
17 new Thread(notify).Start(2);
18 new Thread(notify).Start(3);
19
20 Console.Read();
21 }

代码中,分别输出了通知者的thread id和callback handler的thread id。这里使用的是Rx默认的线程并发方式。输出结果如下:

无论是在当前线程调用,还是新启线程执行,通知者和处理方法所在线程均为同一个。在该示例中,Rx的线程分配是在free-threaded模式下工作的,free-threaded就意味着我们不强行指其Rx中的subscription, notification执行线程。这是Rx的默认工作模式,而这种模式下subscribing/call OnNext并没有引发新的线程来处理observable序列,线处理方式是单线程(Single Threaded Apartment,STA)。所以,我们可以这样说:单线程是Reactive Extensions(Rx)的默认处理方式。

使用SubscribeOn控制订阅(subscribing)的上下文

IObservable<TSource>的扩展方法SubscribeOn<TSource>(IScheduler)允许我们传入一调度器(Scheduler),控制订阅执行的上下文。

 1 static void Main(string[] args)
2 {
3 Console.WriteLine("Starting on threadId:{0}", Thread.CurrentThread.ManagedThreadId);
4 var source = Observable.Create<int>(
5 o =>
6 {
7 Console.WriteLine("Invoked on threadId:{0}", Thread.CurrentThread.ManagedThreadId);
8 o.OnNext(1);
9 o.OnNext(2);
10 o.OnNext(3);
11 o.OnCompleted();
12 Console.WriteLine("Finished on threadId:{0}",
13 Thread.CurrentThread.ManagedThreadId);
14 return Disposable.Empty;
15 });
16 source
17 //.SubscribeOn(Scheduler.ThreadPool)
18 .Subscribe(
19 o => Console.WriteLine("Received {1} on threadId:{0}",
20 Thread.CurrentThread.ManagedThreadId,
21 o),
22 () => Console.WriteLine("OnCompleted on threadId:{0}",
23 Thread.CurrentThread.ManagedThreadId));
24 Console.WriteLine("Subscribed on threadId:{0}", Thread.CurrentThread.ManagedThreadId);
25
26 Console.Read();
27 }

代码中,使用Observable.Create创建一Observable序列,随后订阅该序列。输出结果为:

当序列被订阅source.Subscribe,代理Observable.Create被调用执行。首先是OnNext(1) handler,依次是OnNext(2) OnNext(3) handler和OnCompleted handler,最后执行到“Subscribed on threadId:10”。整个过程是线性的,阻塞(block)式的。这是符合上面分析的Rx默认单线程的模式的。

我们放开.SubscribeOn(Scheduler.ThreadPool)的注释,指定Rx工作在线程池内完成。执行结果如下:

可以看到,所有的handler都是在一新线程内完成的。这是一个非阻塞的(no=-block)模式。

SubscribeOn方法常用来指定Observable notifications的线程执行模式(哪里执行)。其常用于以下的场景中:

  》 UI线程不允许阻塞

  》 不需在UI线程中更新显示

常用的Scheduler属性:

CurrentThread 在当前进程中尽快的调度工作,同步(synchronous,block)
Immediate 在当前进程中立即调度工作,同步(synchronous,block)
NewThread 在新线程中调度工作(asynchronous,no-block)
TaskPool 在任务工厂中调度工作(asynchronous,no-block)
ThreadPool 在线程池中调度工作(asynchronous,no-block)

示例代码 RxConcurrencySample 下载

参考资料:

      The Reactive Extensions(Rx)...

      Reactive Extensions(Rx)介绍

 

Reactive Extensions(Rx)并发浅析的更多相关文章

  1. Reactive Extensions(Rx) 学习

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

  2. Reactive Extensions (Rx) 入门(5) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7749907 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  3. Reactive Extensions (Rx) 入门(4) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7685393 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  4. Reactive Extensions (Rx) 入门(3) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7628322 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  5. Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions

    译文:https://blog.csdn.net/fangxing80/article/details/7581937 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  6. Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要

    译文:https://blog.csdn.net/fangxing80/article/details/7381619 原文:http://www.atmarkit.co.jp/fdotnet/int ...

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

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

  8. Rx (Reactive Extensions)介绍

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

  9. Rx (Reactive Extensions)

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

随机推荐

  1. SQL server 提示“代理XP”被关闭的解决方法

    打开SQL Server Configuration Manager(SQL Server配置管理器),启用SQL Server Agent(SQL Server 代理).

  2. Bombing HDU, 4022(QQ糖的消法)

    Bombing From:HDU, 4022 Submit Time Limit: 4000/2000 MS (Java/Others)      Memory Limit: 65768/65768 ...

  3. JAVA设计模式(08):结构化-飞锤(Flyweight)

    当前咱们国家正在大力倡导构建和谐社会,当中一个非常重要的组成部分就是建设资源节约型社会,"浪费可耻,节俭光荣". 在软件系统中,有时候也会存在资源浪费的情况,比如在计算机内存中存储 ...

  4. Swing开发界面时的一个bug复盘

    问题:QA突然发个截图说一个Dialog上展示的东西变形了 分析:不理解,什么也没做,怎么会变形,刚刚我用的时候还正常.看看代码,的确什么也没更改:在本地测一下,也没有问题:baidu,bing,st ...

  5. 每天进步一点点--&gt;函数fseek() 使用方法

    在阅读代码时,遇到了非常早之前用过的fseek(),非常久没实用了,有点陌生,写出来以便下次查阅. 函数功能是把文件指针指向文件的开头,须要包括头文件stdio.h fseek   函数名: fsee ...

  6. C# 字段、属性、成员变量

    引言: C#与java,C++中的这些基本概念略有不同. 由于easy混淆,所以这里总结下差别. 希望能对刚開始学习的人有帮助! 一.定义与作用 1.字段(field):是C#类级别定义的,和方法同一 ...

  7. 世界杯推动彩票APP爆发,谁将会笑到最后?

        巴西世界杯的火爆上演不只给球迷们带来了一场华丽的足球盛宴,对网络彩票行业而言,这也是一次千载难逢的商机. 只是,并不是全部玩家都能攫取理想的商业利益,网络彩票的角逐宛如世界杯的比赛一样,有人晋 ...

  8. 必须掌握的八个cmd命令

    原文:必须掌握的八个cmd命令 一.ping 它是用来检查网络是否通畅或者网络连接速度的命令.作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的 ...

  9. 前端插件@user

    分享一个 @user 前端插件   开源地址:https://github.com/yuezhongxin/Mention.js 插件效果:类似于微博或 github 中 @user 列表效果. 这是 ...

  10. ORA-00838: Specified value of MEMORY_TARGET is too small(转)

    1. 测试环境OS: RHEL5U5(32bit)DB: Oracle 11.2.0.3.0(32bit) 2.   异常原因. 2.1 oracle 11g默认sga_target为0,如下图, O ...