net内存使用之我所见

  “实践是检验真理的唯一标准”,再多的理论也不如我们的测试。下面我就用代码来测试关于内存问题我们应该如何处理。

  新建一个项目,只要有一个窗体就可以了,再加一个按钮,代码如下,

  

  public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            for(int i=0;i<10;i++)
            {
                Form form = new Form();
                form.Show();
            }
        }
    }

    

  为了让测试更精确,我不在调试下运行程序,而是直接运行bin文件夹下的程序,我们看下面的几个图对比一下:

  net内存使用之我所见  net内存使用之我所见net内存使用之我所见

  第三个图让人有点不可理解,为什么变小了。打开10个空白窗体,好像也不费什么内存,我们给打开的窗体加一个背景看看会怎么样。加载的背景在下面,及测试结果。    

  代码只是改了一下

   for(int i=0;i<10;i++)
            {
                Form form = new Form();
                form.BackgroundImage = Properties.Resources.formbackgroup;
                form.Show();
            }

 

  net内存使用之我所见net内存使用之我所见net内存使用之我所见显然,窗体关闭后,内存也没有被放出来,很多的人可能都知道,NET写出来的程序只要开着不动,隔一天来之后,它都会变得慢。不能释放出来的内存,我们都知道是那个资源文件搞得,既然我们它不能放出来,那我们就要想办法让它放出来,或者想办法,当打开的时候,它不占这么多的内存,这才是正道,办法还是有的,我们只要再改一下代码,立马就会看到效果了。我第一次测试这个问题的时候我就感觉到是资源文件在作怪,我就直接定义了一image的属性,然后把这个属性给打开的窗体,下面是代码和测试结果,估计也是很多人想不到的: 

  


        private Image _bgImage = null;

        public Image BgImage
        {
            get
            {
                if (_bgImage== null)
                {
                    _bgImage = Properties.Resources.formbackgroup;
                }
                return _bgImage;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            for(int i=0;i<10;i++)
            {
                Form form = new Form();
                form.BackgroundImage = BgImage;
                form.Show();
            }
        }

net内存使用之我所见net内存使用之我所见

很明显,同样是同一张图片,可是差了2M的虚拟内存,以下是我的估计,(没有理论根据),当程序加载我们程序中的资源文件时,是每加载一次,就当一个新文件加到内存中,窗体开10个,那就加了10个图片到内存中当,当我定义属性的时候,大家应该知道,图片是一个文件,文件具有唯一性,那么无论你将它给了谁,都是同一个,它也只加载一次,因为我的属性保存证了它只加载一次,这就有点像ado.net中的datatale一样,它也是文件,无论你怎么传,都不用加 ref,可是为什么资源文件不是这样呢,我没有想过资源文件内部是如何读到内存中的。所以当我们以后用到资源文件时,如果这个图片用到很多地方,那这个问题,你不得不考虑一下了。结果测出来明显有差别了,那是否还有更好的办法来处理呢,就比如你就是想直接加载资源文件到控件中,那么你一得要记得,你一定要写代码来将这个背景销毁了,很明显,MS没有帮我们销毁,代码很简单,如下就可以达到了


        private void form_FormClosed(object sender, FormClosedEventArgs e)
        {
            Form f = (Form)sender;
            if (f.BackgroundImage != null)
            {
                f.BackgroundImage.Dispose();
                f.BackgroundImage = null;
            }
        }

  

 大家可能听说过windows003里面有一个叫做emptry的工具,它其实也没什么用,它只是调用了一个API,

 

[DllImport("kernel32.dll")]
        public static extern bool SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);

 

 public static void GarbageCollect()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

                 }

        public static void FlushMemory()
        {
            GarbageCollect();

            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }

 

它的作用和上面的代码的效果是一样的,至少我测试发现是一样的。物理内存减下来,说白了,和没减是一样的,关键是虚拟内存才是问题的所在。不过适时的调用一下上面的还代码,还是会起到微小的作用的,怎么说有总比没有强。写代码时,遇到消耗内存的时候,只要我们多测测,多想想,还是能省点内存的。看似普通的代码(比如上面的资源文件),不测试也不会发现问题的所在。

 

 

  

你可能感兴趣的:(net)