(本帖在版工的旧 Blog 中,发表日期为 2007/05/01)

在 .NET 1.x 的 C#、.NET 2.0 的各种语言中,有所谓的 using statement (如本 blog 上一篇帖子「使用ADO.NET 的NextResult 方法取得多个Result Set」的代码范例),可保证自动 dispose (释放) unmanaged object (对象) 所占用的资源,包括因未处理的 exception 而造成区块结束 (但 StackOverflowException 除外),系统都会 dispose 资源。因此若您在 using 区块中建立了数据库的 connection,即无须再手动 close connection,亦无须再下 Connection.Dispose()、Command.Dispose() 等指令。根据 MSDN Library 和目前市面上几本 ADO.NET 2.0 原文书都有提到,在 using 区块中会自动去做 dispose 的动作。

.NET 的 garbage collector 会自动释放不再使用的 managed resources 所占用的内存,不用程序员手动撰码;但 unmanaged resources 则需要程序员自行下 Dispose() 去做处理,以让对象彻底终止 unmanaged resources 的使用。例如传统的做法,常会在 try-catch-finally pattern 中去呼叫 Dispose 方法;但若是数据库的联机,则必须有不同考虑,因为若任意下 Dispose 提早回收,也可能导致联机无法有效地被重复引用。

现在大部分的数据库和 Data Provider 都有支持 Connection Pooling 机制,亦即在建立完数据库的联机后,当程序员呼叫 Close 方法关闭一个数据库的 Connection 对象时,.NET 的 Data Provider 并不会将这个对象所占用的内存空间释放掉,而是将此对象暂存至 Pool 之中 ,以便待会可以再重复使用。

若在设定时间 (默认为 60 秒) 内,没有应用程序使用到此对象,或是呼叫了 Dispose 方法,则 .NET Data Provider 才会真正关闭这个联机,并由 Garbage Collector 自动将资源收回。因此,常有 web 程序员在网络上各讨论区提到,是否有必要在呼叫 Close 方法后,再呼叫 Dispose 方法,并将 Connection 设为 Nothing (或 Null)?答案是不必要的。因为 GC 过一阵子就会自动回收未再被参照的联机,手动呼叫 Dispose 只不过提早回收的动作而已。而且若是该联机,可能会在短时间内被大量使用者同时存取的话,也应让其待在 Pool 中待命,而应避免手动呼叫 Dispose 方法,导致它被真正关闭并被回收,而无法有效地被重复使用。

由于 GC 只会在系统闲置或内存不足时才启动,因此除非是使用频率非常繁复的资源,否则交由 GC 自行处理即可。而设为 Nothing (或 Null) 也只是将 Connection 变量的位置清除 (Null Reference),事实上原来 New 出来的 Connection 对象还是存在。而 Dispose 方法是用来处理自行建立的 Windows 资源,但又不会自行释放的对象,如档案 (开档与关文件)、GDI 对象 (直接由 Win API 叫用)…等等。

接下来,再回头探讨 .NET 的 VB/C# 语言中都有的 using statement。using 语句算是简易版的 try-finally pattern,可让程序员以较简便的写法尽早去释放资源,尤其最适用在有限的 unmanaged resources 上,例如:档案和串流 I/O、Socket 网络连接、File Handle (档案控制代码)、COM 组件、绘图和字形、数据库存取、WorkflowRuntime (WF)、…等等的内存自动释放。using statement 遇到例外时,也会抛出例外 (throw),但不会去 catch 处理例外;因此若您想要自行处理例外的话,只能回归传统的 try-catch-finally 写法。

提供给 using statement 的对象必须实作 IDisposable 接口。若是自己写的 class,只要实作 System.IDisposable 接口,即拥有 Dispose 方法。之后若引用 using statement 去释放这个 class 的 instance,即会自动做 object 的 Close()、Dispose()、设定为 null (Nothing) 这三种动作,不需要再自己手动处理。反而若是自己手动多下一次 Close(),会让 CLR 浪费资源多做一次处理,反倒会影响程序「性能 (performance)」。根据国外网站及 ADO.NET 2.0 书籍证实,若 using 语句搭配 CommandBehavior.CloseConnection 一起使用,其重复关闭数据库联机的动作,会大幅地降低程序性能,处理时间甚至会多出 84% 以上 (叫用 ExecuteReader() 时,若搭配 CommandBehavior 枚举值 (enumerated value),可要求在查询完成后,自动关闭数据库联机)。

此外,using statement 也可多层巢状地使用,例如:第一层的 using statement 里包 SqlConnection 的宣告及 instance 的新增,第二层包 SqlCommand,第三层包 SqlDataReader。您亦可在巢状的 using statement 中指定多种的系统资源,包括数据库的 transaction 交易处理。

-------------------------------------------------------------------------
参考文件:
[1] 「Prescriptive Architecture - Improving ADO.NET Performance」, MSDN
[2] 「Choose the right .NET data provider, optimize application performance」,  SearchWinDevelopment.com
[3] 多本中英文 ADO.NET 书籍、网络技术文件

转载于:https://www.cnblogs.com/WizardWu/archive/2008/07/13/1241785.html

探讨 .NET 语言的 using statement 与资源释放相关推荐

  1. c语言补码计算方法,探讨C语言学习中补码计算方法.doc

    探讨C语言学习中补码计算方法 探讨C语言学习中补码计算方法 摘要:补码是C语言学习中的一个重点和难点,如何能够快速准确地计算出各个数的补码值得我们探讨.本文从补码的意义入手,采用逆向逻辑思维,分别提出 ...

  2. Linux C语言通过curl下载https资源

    Linux C语言通过curl下载https资源代码如下,注意需要把main函数 char *url 赋值为需要下载文件的路径. #include <curl/curl.h> #inclu ...

  3. 基于 Android NDK 的学习之旅-----资源释放

    基于 Android NDK 的学习之旅-----资源释放 做上一个项目的时候因为与C引擎交互频繁,有时候会突然莫名其妙的的整个应用程序直接挂掉.因为我是学Java 开始的,所以对主动释放内存没多大概 ...

  4. C#内存泄露与资源释放 经验总结

    本文链接:http://blog.csdn.net/yokeqi/article/details/41083939 C#相比其他语言,拥有强大的垃圾回收机制,但并不是这样,你就可以对内存管理放任不管, ...

  5. C语言 游戏人物的移动与技能释放(图形化编程)

    C语言 游戏人物的移动与技能释放(图形化编程) 通过c语言的easyX库来实现人物的移动和技能释放 详细效果和图片看视频演示 https://www.bilibili.com/video/BV18A4 ...

  6. Java8 新的 try-with-resources 语句,自动资源释放

    读取文件后需要释放资源,对于占用内存比较大的,非常重要: (1)读取文件内存占用较多的优化方式: 一次读取部分处理完继续读取,可以有效的减少内存的占用: 使用RandomAccessFile可以从文件 ...

  7. C#资源释放及Dispose、Close和析构方法

    C#资源释放及Dispose.Close和析构方法   备注:此文的部分观点有误,之所以仍旧保留本文,是需要在后期给出一个勘误版.正确的版本在这里"C#中标准Dispose模式的实现&quo ...

  8. rhcs做HA时的资源释放脚本实现

    场景: CentOS6.3的二次封装版本,安装hortonworks的hadoop发行版,并按照其官方文档实现高可用,但无fence设备支持,因此导致断网和断电测试时,备用HA节点无法得到资源释放的通 ...

  9. C#中的非托管资源释放(FinalizeDispose)

    在了解Finalize和Dispose之前,我们需要了解两个概念,一个是托管资源,一个非委托资源. a.其中托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,例如程序中分配的对 ...

  10. c#中的非托管资源释放 (Finalize和Dispose)

    c#中的非托管资源释放 (Finalize和Dispose) 收藏 在了解Finalize和Dispose之前,我们需要了解两个概念,一个是托管资源,一个非委托资源. a.其中托管资源一般是指被CLR ...

最新文章

  1. pcntl_fork 导致 MySQL server has gone away 解决方案
  2. 零基础学习java,这些书一定要看!
  3. 大数据流处理:Flume、Kafka和NiFi对比
  4. 如何洞察行业中的应用场景?(上篇)
  5. java平均差_如何做好描述统计分析
  6. 在Oracle中重编译所有无效的存储过程
  7. windows + cmake + vs2019 编程
  8. xampp mysql 卸载_卸载Xampp并安装apache + mysql + php 过程
  9. 大学c语言项目,项目大学C语言程序设计期末复习重点.doc
  10. linux 好用的命令行软件,比较好用的linux命令
  11. c语言自动存储,C语言存储分类
  12. 关于通过webclient和JSON格式报文与服务器之间通讯的解决方法和遇到的难题
  13. 云服务器怎么多人进去编辑文档,一台云服务器多人使用
  14. Proxmark3的Android客户端,Proxmark3 冰人原版固件及客户端
  15. 机械精度设计与检测|尺寸精度
  16. 关于“未使用GUID分区表”无法安装的解决方案
  17. 致远项目管理SPM系统资源管理之资源台班工时管理
  18. 内存池 - 原理分析(一)
  19. java rgb转yuv_RGB,CMY(K),YUV,YIQ,YCbCr颜色的转换算法(java实现)
  20. dom更新到底在javascript事件循环的哪个阶段?「前端每日一题v22.11.17」

热门文章

  1. docker搭建nginx+php+mysql环境
  2. python数据包之利器scapy用法!
  3. Vue学习笔记进阶篇——多元素及多组件过渡
  4. 实验四+067+冯艳芳
  5. 简易效率的抽奖算法(转)
  6. 全宁对医药行业销售代表的介绍
  7. jquery操作下拉框(select)的一些说明
  8. js动态改变iframe的高度
  9. cakephp 学习1
  10. Android 拦截TextView中超链接点击事件