RX库中的IDisposable对象
IDisposable是.net中的主动资源释放接口,它是在编程过程中经常使用到的一个接口,本文介绍一下微软在Rx.NET中提供的一系列常用的Disposable类,通过它们可以简化我们的程序代码,提高代码质量。
IDisposable:
一个简单的IDisposable接口实现如下
class DisposableObject : IDisposable
{
private readonly string name = null; public DisposableObject(string name)
{
this.name = name;
} public void Dispose()
{
Console.WriteLine("{0} - Disposed", this.name);
}
}
注: 这个例子并不是合适的实现,主要是为了后面的代码演示使用。
ICancelable
RX框架在Disposable接口上扩展了一下,增加了一个查看是否被释放的状态,定义了一个ICancelable接口
public interface ICancelable : IDisposable
{
bool IsDisposed { get; }
}
除了Disposable.Empty外,RX框架提供的都是ICancelable接口对象。
Disposable.Empty
Disposable.Empty返回的是一个没有任何功能的IDisposable对象,是一个IDisposable的NullObject模式的实现。
它的Dispose函数可以使用,但没有任何行为。
Disposable.Create
Disposable.Create可以快速构建一个IDisposable对象,它接受一个委托,当Dispose函数调用时,执行该委托。
var d = Disposable.Create(() =>
{
Console.WriteLine("Disposed");
});
d.Dispose();
BooleanDisposable
BooleanDisposable是一个简单的ICancelable的实现,它的Dispose操作也没有任何行为,但可以查看该函数是否执行过。
var d = new BooleanDisposable();
Console.WriteLine(d.IsDisposed); d.Dispose();
Console.WriteLine(d.IsDisposed);
由于不能控制该对象的Dispose行为,这个对象用得到不是很多,往往用来作为一个开关变量使用。
CancellationDisposable
CancellationDisposable可将一个CancellationTokenSource对象封装为Disposable对象
- 当Dispose函数调用时,调用Cancel函数。
- 查看IsPosed状态时,返回IsCancellationRequested状态
简单的示例如下:
var source = new CancellationTokenSource();
source.Token.Register(() => Console.WriteLine("Cancelled"));
var d = new CancellationDisposable(source);
Console.WriteLine(d.IsDisposed);
Console.WriteLine(source.IsCancellationRequested);
RefCountDisposable
RefCountDisposable也是一个封装型的Disposable对象,不过它是一个引用计数型的封装。
- 新建RefCountDisposable对象后,引用计数为1
- 调用GetDisposable可以生成一个新的引用Disposable封装,引用技术加1
- 调用RefCountDisposable对象和GetDisposable生成的Disposable对象时,引用计数都减1
- 引用计数为0时,释放封装的Disposable对象
这里需要注意的时,当调用RefCountDisposable. Dispose函数时,可能引用计数还不为0,此时还是可以继续调用GetDisposable函数增加引用计数的。
简单的示例如下:
var d = new RefCountDisposable(new DisposableObject("#1"));
var ref1 = d.GetDisposable();
var ref2 = d.GetDisposable();
Console.WriteLine("ref2 - Dispose");
ref2.Dispose();
Console.WriteLine("ref1 - Dispose");
ref1.Dispose();
Console.WriteLine("Dispose");
d.Dispose();
这个类在释放共享资源的时候非常有用,例如我们做视频点播的时候,当有多个客户端点播视频时,每个客户端都需要维护引用计数,当所有客户端都退出的时候,会自动Dispose,注销视频源。
CompositeDisposable
CompositeDisposable用于聚合多个disposable对象,形成一个新的disposable对象,它主要有Add,Clear,Dispose三个函数。
- Add函数将子Disposable对象添加到集合
- Clear函数删除集合类所有的Disposable对象,同时调用子Disposable对象的Dispose函数
- Dispose函数释放CompositeDisposable对象:释放所有子Disposable对象。
- 如果CompositeDisposable对象已经释放,再次调用Add函数时,不会添加到集合,而是直接调用其子对象的Dispose函数。
简单的示例如下:
var d = new CompositeDisposable();
d.Add(new DisposableObject("#1"));
d.Add(new DisposableObject("#2"));
d.Add(new DisposableObject("#3"));
d.Clear();
Console.WriteLine("----------");
d.Add(new DisposableObject("#4"));
d.Add(new DisposableObject("#5"));
d.Add(new DisposableObject("#6"));
d.Dispose();
Console.WriteLine("----------");
d.Add(new DisposableObject("#7"));
ContextDisposable
ContextDisposable对象也是一个复合Disposable对象
- 它主要用于封装一个Disposable对象,将其与一个SynchronizationContext上下文关联,
- 封装后生成的ContextDisposable对象的Disposable函数会Post到上下文线程中执行。
简单的示例如下:
var context = SynchronizationContext.Current;
var obj = new DisposableObject("#1");
var d = new ContextDisposable(context, obj);
d.Dispose();
这个对象用于释放UI对象非常方便,另外,也可以实现用于将一些Dispose函数推送到指定的队列中串行执行,从而避免一些并发问题。
ScheduledDisposable
ScheduledDisposable和ContextDisposable类似,也是用于封装一个Disposable对象,不过它是将其Dispose函数推送到指定的IScheduler中执行。
var scheduler = ThreadPoolScheduler.Instance;
var obj = new DisposableObject("#1");
var d = new ScheduledDisposable(scheduler, obj);
d.Dispose();
SingleAssignmentDisposable
SingleAssignmentDisposable是一个关联型的Disposable对象
- 可以通过它的Disposable属性关联到子Dispose对象。
- 当执行Dispose函数时,执行的是子Dispose对象的Dispose函数,如果没有关联子Dispose对象,则不执行任何操作。
- 已经执行Dispose函数后,再次使用Disposable属性关联后无法关联,直接会调用子对象的Dispose函数。
SingleAssignmentDisposable的关联有一个Single特点,它主要体现为:
- 如果已经通过Disposable属性关联后,再次调用Disposable属性关联时会抛异常
简单的示例如下:
var d = new SingleAssignmentDisposable();
d.Disposable = new DisposableObject("#1");
try
{
d.Disposable = new DisposableObject("#2"); //--- 例外発生
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.Message);
}
d.Dispose();
d.Disposable = new DisposableObject("#3");
输出结果为:
Disposable has already been assigned.
#1 – Disposed
#3 - Disposed
MultipleAssignmentDisposable
MultipleAssignmentDisposable和SingleAssignmentDisposable类似,区别是其关联的multi特性,它的特点是:
- 如果已经通过Disposable属性关联后,再次调用Disposable属性是会覆盖关联
简单的示例如下:
var d = new MultipleAssignmentDisposable();
d.Disposable = new DisposableObject("#1");
d.Disposable = new DisposableObject("#2");
d.Dispose();
d.Disposable = new DisposableObject("#3");
输出结果为:
#2 – Disposed
#3 - Disposed
SerialDisposable
SerialDisposable和SingleAssignmentDisposable也类似,不过它的Disposable属性再次关联的策略是:
- 覆盖关联,同时先释放上一个Disposable对象。
简单的示例如下:
var d = new SerialDisposable();
Console.WriteLine("#1 - Set");
d.Disposable = new DisposableObject("#1");
Console.WriteLine("#2 - Set");
d.Disposable = new DisposableObject("#2");
Console.WriteLine("Dispose");
d.Dispose();
输出结果为:
#1 – Set
#2 – Set
#1 – Disposed
Dispose
#2 – Disposed
#3 – Set
#3 - Disposed
RX库中的IDisposable对象的更多相关文章
- 在EL表达式或者Struts标签库中格式化日期对象,即将Date转换为yyyy-MM-dd格式
一.EL表达式 首先,在jsp页面引入<fmt> tags,<%@ taglib prefix="fmt" uri="http://java.sun.c ...
- vuex中怎么把‘库’中的状态对象赋值给内部对象(三种方法)
一.通过computed的计算属性直接赋值 import store from '@/store/store' export default{ name: 'count', data(){ retur ...
- 在PHP中使用SPL库中的对象方法进行XML与数组的转换
虽说现在很多的服务提供商都会提供 JSON 接口供我们使用,但是,还是有不少的服务依然必须使用 XML 作为接口格式,这就需要我们来对 XML 格式的数据进行解析转换.而 PHP 中并没有像 json ...
- 第一个lucene程序,把一个信息写入到索引库中、根据关键词把对象从索引库中提取出来、lucene读写过程分析
新建一个Java Project :LuceneTest 准备lucene的jar包,要加入的jar包至少有: 1)lucene-core-3.1.0.jar (核心包) 2) lucene- ...
- SharePoint 2013 文档库中PPT转换PDF
通过使用 PowerPoint Automation Services,可以从 PowerPoint 二进制文件格式 (.ppt) 和 PowerPoint Open XML 文件格式 (.pptx) ...
- C#中对IDisposable接口的理解
http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...
- C++模板中的函数对象
在C++模板类map中一个参数为Compare类型,该类型为一个比较函数,其完整定义如下: template< class Key, class T, class Compare = std:: ...
- iOS开发系列--扩展--播放音乐库中的音乐
众所周知音乐是iOS的重要组成播放,无论是iPod.iTouch.iPhone还是iPad都可以在iTunes购买音乐或添加本地音乐到音乐 库中同步到你的iOS设备.在MediaPlayer.fram ...
- [百度空间] [转] 在 Visual C++ 中控制全局对象的初始化顺序
from: http://blog.csdn.net/classfactory/archive/2004/08/07/68202.aspx 在 C++ 中,同一个翻译单位(.cpp文件)里的全局对象的 ...
随机推荐
- Spring Mvc 一个接口多个继承; (八)
在 spring 注解实现里,一个接口一般是不能多继承的! 除非在 bean 配置文件里有 针对这个 实现类的配置: <beans:bean id="icService" c ...
- CMSZU站群管理系统 升级到 v1.8 [源码下载]
CmsZu 简介 CMSZU即CMS族,是个网站内容管理平台,基于PHP+MYSQL技术创建,源码开放. CmsZu 更新说明 V1.8 修改了些bug 完善数据库管理 -> 数据库表管理的 字 ...
- Swagger文档化restful接口
1.注解 @Api:用在类上,说明该类的作用. @ApiOperation:注解来给API增加方法说明. @ApiImplicitParams : 用在方法上包含一组参数说明. @ApiImplici ...
- P4549 【模板】裴蜀定理
题目描述 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1X1+...AnXn>0,且S的值最小 输入输出格式 输入格式: 第一行给出数字N,代表有N个数 下面一行给出 ...
- UVALive 6467 Strahler Order
> 题目链接 题意:给定一个有向图,顶点代表水池,入度为零的定点代表水源,等级是1,他们延河道(有向边)冲撞,对于普通的水池来说,题目给定判断它等级的两个准则,问出度为零的那个点的等级是多少. ...
- Requests中出现大量ASYNC_NETWORK_IO等待
七夕活动,网页显示异常:504 Gateway Time-out The server didn't respond in time.开发询问数据库是否正常,当时正连接在实例上查询数据,感觉响应确实慢 ...
- TensorFlow 从零到helloWorld
目录 1.git安装与使用 1.1 git安装 1.2 修改git bash默认路径 1.3 git常用操作 2.环境搭建 2.1 tensorflow安装 2.2 CUDA安装 2.3 ...
- Mysql导入脚本失败,提示需要SUPER权限
1.删除: /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ 2.查看增删函数有没有重复 3.删除: set GLOBAL log ...
- MySQL5.7 GTID在线开启与关闭【转】
当前场景 当前某些业务还有未开启GTID服务组,升级5.7后,如何检测是否符合开启GTID条件,如何在线修改切换使用GTID:已经升级5.7后,已经开启GTID,如何快速回滚后退: 线上gtid如 ...
- 006使用Grafana展示时间序列数据
简介 Grafana是一个独立运行的系统,内置了Web服务器.它可以基于仪表盘的方式来展示.分析时间序列数据. Grafana支持多种数据源,例如:Graphite.OpenTSDB.InfluxDB ...