c#:使用using关键字自动释放资源未必一定就会有明显好处

 

记录这篇文章的灵感来源来自今天下班前与同事的小小争论,我现在开发的一个项目中,有这样一段代码:

public string ToXML()
        {
            string strXml = string.Empty;
            try
            {
                MemoryStream ms = new MemoryStream();
                XmlSerializer xml = new XmlSerializer(this.GetType());
                xml.Serialize(ms, this);
                byte[] arr = ms.ToArray();
                strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);
                return strXml;
            }
            catch
            {
                return "";
            }
        }

  同事说象MemoryStream这类资源,应该用using包起来自动释放资源,否则会有内存泄漏问题。在using的使用上,我也同意应该使用using,但由于这类风格的代码在原项目中非常多(有一部分历史原因),如果一一修改,工作量太大,时间不允许。于是我就在内心评估:如果不改,现在这种代码的风险到底有多大?

我想很多人都知道using(Resource res = new Resrouce){},其实相当于

Resource res = new Resrouce

try{}

catch{}

finally{res.Dispose();}

对比与现有代码的区别,无非就是资源没有调用Dispose()释放,但是CLR有强大的GC(垃圾回收)机制,方法调用完成后,方法体中创建的托管资源如果不再被使用,也一并会被GC列为可回收对象,所以就算开发人员没有手动调用Dispose,其实CLR也会帮我们做这件事情,只是时机可能会晚一些而已。

于是有了下面的测试:

1.先创建一个示例用的Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;

namespace Model
{
    public class SampleClass
    {
        public string Name { set; get; }

        public string ToXMLNoUsing()
        {
            string strXml = string.Empty;
            try
            {
                MemoryStream ms = new MemoryStream();
                XmlSerializer xml = new XmlSerializer(this.GetType());
                xml.Serialize(ms, this);
                byte[] arr = ms.ToArray();
                strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);
                return strXml;
            }
            catch
            {
                return "";
            }
        }

        public string ToXMLWithUsing()
        {
            string strXml = string.Empty;
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    XmlSerializer xml = new XmlSerializer(this.GetType());
                    xml.Serialize(ms, this);
                    byte[] arr = ms.ToArray();
                    strXml = Encoding.UTF8.GetString(arr, 0, arr.Length);

                }
                return strXml;

            }
            catch
            {
                return "";
            }
        }

    }
}

  

这其中的ToXML为了测试方便,故意分成了二个版本(一个不用using,一个用using)

2.再创建一个Console程序(命名为WithUsing),写一段测试代码:

using System;
using System.Diagnostics;
using Model;

namespace WithUsing
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始折腾-WithUsing...");
            Stopwatch watch = new Stopwatch();
            int max = 100000;

            watch.Reset();
            watch.Start();

            for (int i = 0; i < max; i++)
            {
                SampleClass c = new SampleClass() { Name = i.ToString().PadLeft(1024, '0') };
                c.ToXMLWithUsing();
            }
            watch.Stop();
            Console.WriteLine("完成,{0}次操作共耗时:{1}毫秒,平均{2}毫秒/次!", max, watch.ElapsedMilliseconds, watch.ElapsedMilliseconds /(decimal)max);
            Console.ReadKey();
        }
    }
}

  

3.再创建一个Console程序(命名为NoUsing),写一段测试代码:

using System;
using System.Diagnostics;
using Model;

namespace NoUsing
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始折腾-NoUsing...");
            Stopwatch watch = new Stopwatch();
            int max = 100000;

            watch.Reset();
            watch.Start();
            for (int i = 0; i < max; i++)
            {
                SampleClass c = new SampleClass() { Name = i.ToString().PadLeft(1024, '0') };
                c.ToXMLNoUsing();
            }

            watch.Stop();
            Console.WriteLine("完成,{0}次操作共耗时:{1}毫秒,平均{2}毫秒/次!", max, watch.ElapsedMilliseconds, watch.ElapsedMilliseconds / (decimal)max);
            Console.ReadKey();
        }
    }
}

  

编译后,同时运行这二个程序,同时利用任务管理器观察内存使用情况:

反复多次运行比较,发现其实二者占用的内存几乎完全相同,这说明GC还是很给力的!

而且从执行时间上看,不用Using,反而更快,这也容易理解:用Using相当于每次都要调用Dispose()方法,这会带来一些系统开销;而不用Using,GC会在适当的时机批量回收资源,性能反而更好。(当然:这个结论不是要误导大家不用using,对于using还是推荐使用的!我的用意在于大家对于一些具体问题要具体分析,不可纯教条主义,一味迷信某些主流的观点)

 

 

时间: 2024-11-01 00:23:32

c#:使用using关键字自动释放资源未必一定就会有明显好处的相关文章

DEDECMS添加软件时关键字自动从TAG获取

最近在帮朋友做一个游戏软件站,在添加测试文章的时候发现一个问题:软件频道不能像文章频道那样关键字自动从TAG中获取,而是直接从标题中分解出一些毫无意义的关键字,这也导致在调用"相关文章"时文章不相关的现象,经过对比文章频道添加模板,我找到了修改方法: 在网站根目录下找到文件 dede/templets/soft_add.htm (dede为DEDECMS默认后台管理目录,如有修改请找到相应的文件夹),打开后找到: <input name="tags" type

jQuery实现搜索关键字自动匹配提示方法

在现在的Web设计中,提高用户体验是企业最为注重的内容之一.在搜索表单中,根据输入的部分内容进行关键字匹配提示功能,就是最直观和常用的交互体验,类似功能已经被多数的互联网网站应用.例如Google的搜索框效果如下: 这里介绍一个jQuery实现搜索关键字自动匹配提示方法.jQuery AutoComplete 是一个基于jQuery实现搜索关键字自动匹配提示的插件,该插件可扩展性强,表现性能优越,方便整合到自己的项目中使用:兼容IE 6.0+, FF 2+, Safari 2.0+, Opera

Jquery插件仿百度搜索关键字自动匹配功能_jquery

本文实例为大家分享了Jquery搜索关键字自动匹配功能的实现代码,供大家参考,具体内容如下jQuery AutoComplete 是一个基于jQuery实现搜索关键字自动匹配提示的插件,该插件可扩展性强,表现性能优越,方便整合到自己的项目中使用:兼容IE 6.0+, FF 2+, Safari 2.0+, Opera 9.0+, and Chrome 1.0+ 等主流浏览器. 下面是具体的使用方法: 1.使用设置 首页,要把插件的js代码嵌入到你自己的项目中去. 复制代码 代码如下: <scri

基于jQuery实现搜索关键字自动匹配功能_jquery

今天我们就一起来看一个简单的基于jquery的关键字自动匹配的例子,希望文章能够对各位有帮助.例子一 在项目中,有时候需要用户选择城市,但是城市太多,用户选择起来不太方便,所以提供了一个用户可以通过输入框输入城市的汉字或者拼音简写.结果示意图如下: 当输入拼音后结果示意图如下: 实现代码如下: <html><head><title>实时查询城市通过姓名或拼音简写</title></head><meta charset = "utf

帝国cms内容关键字自动加链接且设置内容关键字只替换一次

网站上线前先设置一些内部链接对后期的优化排名很有帮助,帝国cms也可以设置文章中的关键字自动加链接,但是要注意一下关键词替换次数,最好是1次. 怎么操作呢?分两步完成 1.帝国cms文章关键字自动加链接:后台 - 其他 - 管理内容关键字 - 在框中添加关键词和链接 2.设置关键词只显示一次(关键词链接只替换一次) 后台 - 系统 - 系统 - 系统设置 - 系统参数设置 - 信息设置 找到"信息内容关键字重复替换",把默认的"0"改成"1" 帝

jQuery实现搜索关键字自动匹配的例子

例子一, 在项目中,有时候需要用户选择城市,但是城市太多,用户选择起来不太方便,所以提供了一个用户可以通过输入框输入城市的汉字或者拼音简写.结果示意图如下:    当输入拼音后结果示意图如下:   实现代码如下: <html><head><title>实时查询城市通过姓名或拼音简写</title></head><meta charset = "utf-8" ><script type="text/j

如何使Windows系统自动释放资源

  自动释放系统资源在Windows中每运行一个程序,系统资源就会减少.有的程序会消耗大量的系统资源,即使把程序关闭,在内存中还是有一些没用的DLL文件在运行,这样就使得系统的运行速度下降.不过我们可以通过修改注册表键值的方法,使关闭软件后自动清除内存中没用的DLL文件及时收回消耗的系统资源.打开注册表编辑器. 找到"HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionexplorer"主键 在右边窗口单击右键,新建一个名为&

JDK1.7中新增自动释放资源接口AutoCloseable

新增了try-with-resource 异常声明 在JDK7中只要实现了AutoCloseable或Closeable接口的类或接口,都可以使用try-with-resource来实现异常处理和资源关闭 异常抛出顺序.在Java se 7中的try-with-resource机制中异常的抛出顺序与Java se 7以前的版本有一点不一样. 是先声明的资源后关闭 JDK7以前如果rd.readLine()与rd.close()(在finally块中)都抛出异常则只会抛出finally块中的异常,

jquery 结合C#后台的数组对文章的关键字自动添加链接的代码_jquery

当我们需要在后台读取多个关键字时,我们可以先把后台的数据库读取到一个数组中(在数据库添加多个关键词时用","隔开): 复制代码 代码如下: public string[] str; //添加一个公共数组一遍jquery调用 protected void Page_Load(object sender, EventArgs e) { string str1 = 读取数据库的关键词; str=str1.Split(','); } 页面的JQuery: <html s> <