在天空飞翔
博客园
首页
新随笔
联系
订阅
管理
随笔 - 22 文章 - 0 评论 - 63 trackbacks - 1
<
2007年12月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
与我联系
发短消息
常用链接
我的随笔
我的空间
我的短信
我的评论
更多链接
我的参与
我的新闻
最新评论
我的标签
留言簿
(1)
给我留言
查看留言
我的标签
mp3
(1)
分类
(1)
c#
(1)
随笔分类
C#(12)
链接(1)
休闲(8)
随笔档案
2008年7月 (1)
2008年5月 (2)
2008年4月 (1)
2008年3月 (1)
2008年1月 (3)
2007年12月 (6)
2007年8月 (1)
2007年7月 (1)
2007年6月 (3)
2007年5月 (3)
搜索
最新评论
1. re: 电饭煲是如何知道饭已熟了的
果然BH啊!!!
--Jackei
2. re: 电饭煲是如何知道饭已熟了的
搞笑。。。
--ubun
3. re: 支持函数,变量的算术表达式计算(三、加入函数)
关于您的提示“参数名称和参数个数一定要设置正确,否则在解析的时候会出错”,必须在写函数的时候就指定参数个数吗?如果参数的个数不确定该怎么办啊?比如我准备增加一个MIN函数,来获取数组中的最小值,但这个...
--hj6
阅读排行榜
1. 正确实现 IDisposable 接口(2186)
2. 支持函数,变量的算术表达式计算(三、加入函数)(2175)
3. 支持函数,变量的算术表达式计算(二、中缀转后缀)(1680)
4. 支持函数,变量的算术表达式计算(一、计算后缀表达式)(1519)
5. [源码]用c#创建支持多语言的应用程序(949)
评论排行榜
1. 支持函数,变量的算术表达式计算(一、计算后缀表达式)(15)
2. 正确实现 IDisposable 接口(12)
3. 支持函数,变量的算术表达式计算(二、中缀转后缀)(11)
4. 支持函数,变量的算术表达式计算(三、加入函数)(6)
5. [源码]一个简单的源代码行数统计器(6)
正确实现 IDisposable 接口
前言: 之前在M$的一本工具书上看过该节内容,但慢慢地就忘记了, 在实际项目遇到类似的问题又要 google, 汗下, 于是写此篇blog作备忘录 。
虽然 .net 有垃圾回收机制(GC), 可自动进行大部分的资源清理工作,但开发人员仍旧应该养成良好的通过手动调用资源清理方法来进行资源回收的习惯, 让对象实现
IDisposable
接口正是 M$ 所推荐的, 该接口的原型为:
//
Summary:
//
Defines a method to release allocated unmanaged resources.
[ComVisible(
true
)]
public
interface
IDisposable
{
//
Summary:
//
Performs application-defined tasks associated with freeing, releasing, or
//
resetting unmanaged resources.
void
Dispose();
}
注:.net 内部也有传说中的”析构函数“,就是
Finalize()
, 该函数由GC自动调用。
实现 Dispose 需要注意的是
1. 如果资源已手动释放过了,就应该通知GC,不要再对该对象执行 Finalize 操作
2. 确保重复执行 Dispose 时不会出错
根据以上规则, 简单的定义一个类 classSample
public
class
classSample : IDisposable
{
/**/
///
<summary>
///
该对象是否已被销毁过
///
</summary>
private
bool
disposed;
/**/
///
<summary>
///
这就是传说中的 Finalize函数,是不是和C++的析构函数很像?
///
</summary>
~
classSample()
{
Console.WriteLine(
"
对象被销毁
"
);
Dispose(
false
);
}
public
void
Dispose()
{
Console.WriteLine(
"
手动销毁对象
"
);
Dispose(
true
);
//
通知GC, 偶已经被销毁过了,可以不用在管偶了。。。
GC.SuppressFinalize(
this
);
}
/**/
///
<summary>
///
Dispose
///
</summary>
///
<param name="disposing">
是否由程序直接调用
</param>
protected
void
Dispose(
bool
disposing)
{
if
(
!
disposed)
{
if
(disposing)
{
//
该函数为手动调用,此处可进行托管资源的清理
//
比如此类中有一个类型为 DataSet 的变量 dsData
//
此处可调用该对象的 Dispose 方法来清理托管资源
dsData.Dispose();
}
//
进行非托管资源的清理
//
非托管的资源主要为一些用 API 打开的文件句柄,设备场景句柄等
//
该类资源 GC 是无法管理的,只能依靠程序员自已释放
//
不同的资源, 释放方法不一样
//
释放文件句柄 (定义API的代码略。)
CloseHandle(handle);
//
释放GDI 中的设备场景 (定义API的代码略。)
ReleaseDC(hdc);
}
disposed
=
true
;
}
}
注意
protected
void
Dispose(
bool
disposing) 函数, 清理托管资源和非托管资源的代码位置不要写反了,否则当一个托管对象已经被GC回收后,再去调用它的Dispose 方法, 系统会触发一个 ObjectDisposedException 异常
到这里 ,一个简单的实现
IDisposable 的类已经写好了, 再写段测试代码看看
private
void
button1_Click(
object
sender, EventArgs e)
{
classSample cls
=
new
classSample();
}
点击按钮, 再关闭程序, 可看到 output 窗口中显示
对象被销毁
说明 Finalize 函数被执行了
换一个
private
void
button1_Click(
object
sender, EventArgs e)
{
classSample cls
=
new
classSample();
cls.Dispose();
}
再看 output 窗口中,只显示了”手动销毁对象“, 说明在手动执行Dispose 后,已正确通知GC,不再执行
Finalize函数。
小技巧: 可使用 using 关键字来定义对象的生存期,
超出 using范围 后,如果对象实现了
IDisposable接口, 系统会自动调用其 Dispose 方法, 是不是很方便。
using
(classSample cls
=
new
classSample())
{
}
看,我并没有调用 Dispose 方法, output 窗口中还会显示 ”手动销毁对象“.
posted on 2007-12-28 16:08
在天空飞翔
阅读(2186)
评论(12)
编辑
收藏
所属分类:
C#
FeedBack:
#1楼
2007-12-28 16:25
装配脑袋
问题的关键在于,有人不知道什么叫“非托管资源的清理”,以至于还是不能正确实现Dispose
回复
引用
查看
#2楼
2007-12-28 17:38
Terry Sun
实用的文章
偶在上一个项目中有用到了继承IDisposable的方法,Dispose(bool disposing)
这个方法比偶写的巧,3Q
回复
引用
查看
#3楼
2007-12-28 18:56
辰
说了还是没说。
到底怎么从内存清理。
GC.SuppressFinalize(this);
这句话根本没用
回复
引用
查看
#4楼
2007-12-28 20:32
望穿秋水
//该函数为手动调用,此处可进行托管资源的清理
这里具体该怎样写对象的释放?很不解?
回复
引用
查看
#5楼
2007-12-28 23:28
Cat Chen
我觉得这个写法是线程不安全的。
回复
引用
查看
#6楼
2007-12-29 01:44
Henry Liang
@装配脑袋
你说的有道理。
回复
引用
查看
#7楼
2007-12-29 02:48
corvallis [未注册用户]
My 2 cents:
In Dispose method, maybe move GC.SuppressFinalize(this) above the Dispose(True) call. It is a little better to inform GC ealier.
Simliarly, move disposed=true just after the if condition. This can help reducing the thread-safety issue since release unmanaged resource can take a while. (not 100% although)
回复
引用
#8楼
2007-12-29 09:12
Anytao
常见的非托管资源包括:文件句柄、数据库链接、位图、网络链接、COM对象、互斥体等,使用Dispose就得了解哪些资源在这里释放。
推荐同时实现Finalize和Dipose,以确保非托管资源一定被释放。
回复
引用
查看
#9楼
2007-12-29 10:03
michaelhuwei [未注册用户]
@辰
GC.SuppressFinalize(this); 这句话怎么会没用呢?
加了这句后, Finalize 方法就不会执行了,文章中不是说了吗?
回复
引用
#10楼
2007-12-29 10:05
michaelhuwei [未注册用户]
--引用--------------------------------------------------
装配脑袋: 问题的关键在于,有人不知道什么叫“非托管资源的清理”,以至于还是不能正确实现Dispose
--------------------------------------------------------
#8楼 2007-12-29 09:12 Anytao
已经回答了, 不同的非托管资源, 清理方法不一样啊, 比如打开的文件句柄要用 CloseHandle 关掉, GDI 的DC 要用 ReleaseDC 关掉,等
回复
引用
#11楼
2007-12-29 12:16
芭蕉
.Net components上有一个实现我觉得还不错,感兴趣的可以去看看,Lifecycle Management那一章的最后一个例子就是了。
回复
引用
查看
#12楼
2007-12-29 14:00
BlueMountain
Jeffrey Richter. net框架程序设计技术内幕, 李建忠翻译, 说得非常清楚了。
回复
引用
查看
社区
新闻
新用户注册
刷新评论列表
标题
姓名
主页
Email
(只有博主才能看到)
验证码
*
看不清,换一张
[
登录
][
注册
]
内容(请不要发表任何与政治相关的内容)
Remember Me?
登录
使用高级评论
新用户注册
返回页首
恢复上次提交
[使用Ctrl+Enter键可以直接提交]
该文被作者在 2007-12-29 10:16 编辑过
另存
打印
所属分类的其他文章:
·
一个小程序
·
将程序加到启动组
·
mp3 分类管理工具
·
支持函数,变量的算术表达式计算(三、加入函数)
·
支持函数,变量的算术表达式计算(二、中缀转后缀)
·
支持函数,变量的算术表达式计算(一、计算后缀表达式)
·
正确实现 IDisposable 接口
·
为应用程序添加消息过滤器
·
[源码]类似于 word 的颜色选择器 ColorPicker
·
[源码]用c#创建支持多语言的应用程序
最新IT新闻:
·
浅析facebook的信息架构
·
Mozilla将于本周五发布Firefox 3.1第一个预览版
·
瑞星将向个人用户免费1年
·
中国互联网历史上最伟大的产品TOP10(二)
·
盖茨官方否认天价租楼看奥运 纯属地产商炒作
博客园新闻频道
博客园首页
社区