.NET陷阱 三 “正确”使用控件也会造成内存泄露

在我们的代码中,有时会在控件中添加对数据对象的引用。比如使用树节点的Tag属性保存相应的对象,以便在界面操作中能简单的进行访问。因为其它地方不会引用这些数据,所以我们期望在控件被销毁时,垃圾回收机制能回收相应的内存。但当软件运行了一段时间后,内存使用量会变得非常大。下面是简化后的示例代码:

using System;
 using System.Windows.Forms;   

 namespace MemoryLeak
 {
     public class MainForm : Form
     {
         private Button holderButton;
         private Button controlButton;
         private FlowLayoutPanel panel;
         private object checkGc;   

         public MainForm()
         {
             DumpMemoryUsage("before allocate checkGc.");
             checkGc = MakeLargeObject();
             DumpMemoryUsage("after allocate checkGc.");   

             holderButton = new Button();
             holderButton.Enabled = false;
             holderButton.AutoSize = true;
             holderButton.Text = "The button holds large object.";
             DumpMemoryUsage("before allocate holderButton.Tag.");
             holderButton.Tag = MakeLargeObject();
             DumpMemoryUsage("after allocate holderButton.Tag.");   

             controlButton = new Button();
             controlButton.AutoSize = true;
             controlButton.Text = "The button controls holderButton.";
             controlButton.Click += (sender, e) =>
             {
                 DumpMemoryUsage("before release checkGc and holderButton.Tag.");
                 panel.Controls.Remove(holderButton);
                 holderButton.Dispose();
                 holderButton = null;   

                 checkGc = null;
                 DumpMemoryUsage("after release checkGc and holderButton.Tag.");
             };   

             panel = new FlowLayoutPanel();
             panel.AutoSize = true;
             panel.FlowDirection = FlowDirection.TopDown;
             panel.Controls.Add(controlButton);
             panel.Controls.Add(holderButton);   

             Controls.Add(panel);
         }       

         private void DumpMemoryUsage(string msg)
         {
             GC.Collect();
             Console.WriteLine(msg);
             Console.WriteLine(GC.GetTotalMemory(true));
         }   

         private object MakeLargeObject()
         {
             var largeObject = new object[100];
             for (int i = 0; i < largeObject.Length; ++i)
             {
                 var array = new int[100][];
                 largeObject[i] = array;
                 for (int j = 0; j < array.Length; ++j)
                 {
                     array[j] = new int[100];
                 }
             }   

             return largeObject;
         }
     }   

     static class Program
     {
         static void Main()
         {
             Application.Run(new MainForm());
         }
     }
 }

代码中的checkGc变量是为了在输出中确认垃圾回收已经进行了。下面是输出结果:

before allocate checkGc.
 281576
 after allocate checkGc.
 4605632
 before allocate holderButton.Tag.
 4606384
 after allocate holderButton.Tag.
 8930480
 before release checkGc and holderButton.Tag.
 8940016
 after release checkGc and holderButton.Tag.
 4616824

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索private
, tag
, panel
, #FlowLayoutPanel
, before
after
造成内存泄露的原因、隐私泄露造成的危害、野外陷阱正确设置法、cell控件是否正确安装、打印控件没有正确安装,以便于您获取更多的相关知识。

时间: 2024-12-20 11:47:12

.NET陷阱 三 “正确”使用控件也会造成内存泄露的相关文章

.Net WInform开发笔记(三)谈谈自制控件(自定义控件)_C#教程

末日这天写篇博客吧,既然没来,那就纪念一下. 这次谈谈自制控件,也就是自定义控件,先上图,再说 1.扩展OpenFileDialog,在OpenFileDialog中添加各种文件(.txt,.jpg,.excel等等)的预览功能 开发笔记(三)谈谈自制控件(自定义控件)_C#教程-winform自定义控件"> 2.重写ListBox,增加折叠.鼠标背影.分类等功能 -----------------------------分割线-------------------------------

在ASP.NET中用三个DropDownList控件方便的选择年月日

asp.net|控件 aspx页面上有三个DropDownList控件, DropDownList1 表示年,DropDownList2表示月,DropDownList3表示天:注意用将这三个DropDownList控件的AutoPostBack属性设为True. 用户可以方便地选择年月日,并且每月的日期会随着用户选择不同的年,月而发生相应的变化 其后台cs文件代码如下: private void Page_Load(object sender, System.EventArgs e) { Da

ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇

好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点 :添加事件. ASP.NET的开发都是事件驱动的,现在我们就来为控件添加事件.在说事件之前,希望大家对C#的语法 要熟悉,对委托很事件要懂. 其实定义事件的步骤很简单: 1.声明一个委托. 2.定义一个携带事件信息的类. 3.定义事件4.定义一个通事件发生后,通知其他对象的方法首先来理清一下我们的思路: 1.在下拉框中选中一个值,并且在输入框中也输入相应的值. 2.我们在页面点击"提交"按钮,按钮

Android学习自定义View(三)——自绘控件和组合控件

MainActivity如下: package cc.testviewstudy3; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.app.Activity; /** * Demo描述: * 关于自定义View的学习(三) * * 自定义View的实现方式大概可以分为三种: * 自绘控件.组合控件.以及继承控件 * 在此Dem

Windows SDK笔记(三):定制控件消息处理函数

一.概述 控件的消息处理函数是由系统定义好了的,通常情况下,不需要自己提供. 但当需要对控件进行特殊控制时,可以提供一个消息处理函数,替换原来的消息处理函数. 自己的处理完成后,再调用控件的缺省消息处理. 二.相关函数 1.窗口类的属性可以通过GetWindowLong和SetWindowLong进行读取和设置 LONG GetWindowLong( HWND hWnd, // handle to window int nIndex // offset of value to retrieve

ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事 件是行不通.如果大家开发的是WinForm中的事件,之前的定义可能没有什么大的问题,只是在效率方法 欠考虑而且,还是可以运行的. 下面我们就回到ASP.NET中的事件. 大家也许看了我们之前定义的事件,确实,事件一般是那么定义的,但是那样定义事件后的,运行起 来的效率不搞,因为那样定义事件后,编译器在编译事件代码的时候,会自动的为我们加入很多多线程安 全的代码,就是说,虽然我们只是定义几行代码,大但

WinForm控件开发总结(三) 认识WinForm控件常用的Attribute

在前面的文章里我们制作了一个非常简单的控件.现在我们回过头来看看这些代码透露出什么信息. 这个类是直接从Control类派生出来的,自定义控件都是直接从Control类派生出来的.这个类定义了 一个属性TextAlignment,用来控制文本在控件中显示的位置: [ Category("Alignment"), Description("Specifies the alignment of text.") ] public ContentAlignment Text

艾伟:WinForm控件开发总结(三)------认识WinForm控件常用的Attribute

      在前面的文章里我们制作了一个非常简单的控件.现在我们回过头来看看这些代码透露出什么信息. 这个类是直接从Control类派生出来的,自定义控件都是直接从Control类派生出来的.这个类定义了一个属性TextAlignment,用来控制文本在控件中显示的位置:               [        Category("Alignment"),        Description("Specifies the alignment of text."

控件-delphi dll rave 内存出错

问题描述 delphi dll rave 内存出错 dll文件中含有rave报表控件.现场少数电脑打开该dll会报内存错误.[read of address 00000000]