TabControl与UserControl合伙吃内存
2010-04-23 01:55 苏飞 阅读(5165) 评论(30) 编辑 收藏 举报先说一下问题的所在吧,公司的项目最近发现越来越慢一直找不到原因,主要是在加载 的时候比较慢,如果是512的内存可能要上分钟了,以前是很快的,我打开内存管理 工具一看我的天那200MB,这也太多了,我记得刚开始只有30MB左右,这是怎么回事呢?先看看我们的系统是这样的我放个图片上来吧,
左面是一个Tree,右面是一个TabControl,单击Tree里会把一个UserControl添加到TabControl里大家一看应该就明白了
我做了一个测试,才明白,我打开我们的系统一面单击一面看内存变化,我每单击一个项目会增加内存2MB左右,开始我没有认为有什么问题,因为这基本是正常的,可是当我把打开的用户控件再次关闭再打开时发现内存还在增加,再点一下又增加,也就是说单击同一个时在增加内存
这是怎么回事呢,我看了一直Tree的单击事件才明白
大家可以看一下以下的代码
private void treeView1_MouseClick(object sender, MouseEventArgs e)
{
try
{
if (e.Button == MouseButtons.Left)
{
Point ClickPoint = new Point(e.X, e.Y);
TreeNode CurrentNode = treeView1.GetNodeAt(ClickPoint);
if (CurrentNode != null)//判断你点的是不是一个节点
{
treeView1.SelectedNode = CurrentNode;//选中这个节点
}
//如果是上层节点则展开之
if (treeView1.SelectedNode.Parent == null)
{
if (treeView1.SelectedNode.IsExpanded == false)
{
treeView1.SelectedNode.Expand();
}
}
else
{
//验证权限不要删除动0不存在1存在2是查询失败
if (user.checkofficeinfoFunction(OfficeInfo.ofPara1, Convert.ToInt32(CurrentNode.ToolTipText.ToString().Trim())
, OfficeInfo.ofId) == 1)
{
//加载窗体
switch (CurrentNode.Text.Trim())
{
case "中国移动":
SystemMusic.Mobile(false);
Mobile Mobile_frm = new Mobile(OfficeInfo);
Mobile_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Mobile_frm);
break;
case "中国联通":
SystemMusic.Unicom(false);
ClientSystem.China_Unicom.Unicom Unicom_frm = new ClientSystem.China_Unicom.Unicom(OfficeInfo);
Unicom_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Unicom_frm);
break;
case "中国电信":
SystemMusic.Telecom(false);
Telecom Telecom_frm = new China_Telecom.Telecom(OfficeInfo);
Telecom_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Telecom_frm);
break;
case "全国缴费":
SystemMusic.National_Mobile_Result(false);
NationalMobile objNationalMobile = new NationalMobile();
objNationalMobile.OfficeInfo = this.OfficeInfo;
objNationalMobile.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, objNationalMobile);
break;
//在这里添加新的栏目
default:
MessageBoxForm objform = new MessageBoxForm("您没有操作此栏目的权限,如有问题请与服务商联系!!!", "提示信息", MessageBoxIcon.Information);
objform.ShowDialog();
break;
}
}
else
{
MessageBoxForm objform = new MessageBoxForm("您没有操作此栏目的权限,如有问题请与服务商联系!!!", "提示信息", MessageBoxIcon.Information);
objform.ShowDialog();
}
}
}
}
catch (Exception ex)
{
MessageBoxForm objform = new MessageBoxForm("提交超时" + ex.Message.ToString(), "提示信息");
objform.ShowDialog();
}
}
不知道 大家有没有看出来这里有什么问题,其实问题就在这些代码
这是生成的一个用户控件的对象然后添加到TabControl里,当然这样是没有问题的,然而有问题的是我每次都 要创建一个新的对象出来,这样一来的话,就是我上面测试的那样只要单击一次就会创建一个新的对象,而又没有关闭之前的对象,当然会每单击一次就增加内存了,看到这里我下了一跳,怪不得最近都 有人说我们的系统慢的要死,我想不慢才怪呢?那现在怎么办呢,只要想办法解决了
我们必须在创建一个新的对象前关闭之前的对象,可是这样应该怎么做呢,我所性就不创建,或是只创建一次,那这样不就没有问题了吗?
我是这样来写的,我把所有要用到的用户控件先定义出来
/// 火车票
/// </summary>
private tranMain objtranMain = null;
/// <summary>
/// 短信
/// </summary>
private SmsMain objSmsMain = null;
/// <summary>
/// 联通固话
/// </summary>
private UnicomPhone objUnicomPhone = null;
/// <summary>
/// 电信固话
/// </summary>
private TelecomPhone objTelecomPhone = null;
/// <summary>
/// 全国游戏
/// </summary>
private NationalMobile objNationalMobile = null;
然后把上面的一段代码稍加改动就可以了,只要我们不是每次都 New一个新的就行
private void treeView1_MouseClick(object sender, MouseEventArgs e)
{
try
{
if (e.Button == MouseButtons.Left)
{
Point ClickPoint = new Point(e.X, e.Y);
TreeNode CurrentNode = treeView1.GetNodeAt(ClickPoint);
if (CurrentNode != null)//判断你点的是不是一个节点
{
treeView1.SelectedNode = CurrentNode;//选中这个节点
}
//如果是上层节点则展开之
if (treeView1.SelectedNode.Parent == null)
{
if (treeView1.SelectedNode.IsExpanded == false)
{
treeView1.SelectedNode.Expand();
}
}
else
{
//验证权限不要删除动0不存在1存在2是查询失败
if (user.checkofficeinfoFunction(OfficeInfo.ofPara1, Convert.ToInt32(CurrentNode.ToolTipText.ToString().Trim())
, OfficeInfo.ofId) == 1)
{
//加载窗体
switch (CurrentNode.Text.Trim())
{
case "中国移动":
SystemMusic.Mobile(false);
if (Mobile_frm == null)
Mobile_frm = new Mobile(OfficeInfo);
Mobile_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Mobile_frm);
break;
case "中国联通":
SystemMusic.Unicom(false);
if (Unicom_frm == null)
Unicom_frm = new ClientSystem.China_Unicom.Unicom(OfficeInfo);
Unicom_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Unicom_frm);
break;
case "中国电信":
SystemMusic.Telecom(false);
if (Telecom_frm == null)
Telecom_frm = new China_Telecom.Telecom(OfficeInfo);
Telecom_frm.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, Telecom_frm);
break;
case "全国缴费":
SystemMusic.National_Mobile_Result(false);
if (objNationalMobile == null)
objNationalMobile = new NationalMobile();
objNationalMobile.OfficeInfo = this.OfficeInfo;
objNationalMobile.Parent_Main = this;
addTabControl(CurrentNode.Text, CurrentNode.Text, MainTabControl, objNationalMobile);
break;
//在这里添加新的栏目
default:
MessageBoxForm objform = new MessageBoxForm("您没有操作此栏目的权限,如有问题请与服务商联系!!!", "提示信息", MessageBoxIcon.Information);
objform.ShowDialog();
break;
}
}
else
{
MessageBoxForm objform = new MessageBoxForm("您没有操作此栏目的权限,如有问题请与服务商联系!!!", "提示信息", MessageBoxIcon.Information);
objform.ShowDialog();
}
}
}
}
catch (Exception ex)
{
MessageBoxForm objform = new MessageBoxForm("提交超时" + ex.Message.ToString(), "提示信息");
objform.ShowDialog();
}
}
这样我测试了一下,当然再每打开新项目是会增加内存这是没有办法 的,但是 在重复单击一个项目时就不会增加内存了,因为它会是同一个对象,如果对象为Null的时候 我才会再次创建, 而且 在每次关闭一个选项卡时我都这样处理一下,调用 一个释放空间的方法UserDispose
/// 释放用户控件资源
/// </summary>
private void UserDispose(string name)
{
switch (name)
{
case "中国移动":
Mobile_frm.Dispose();
Mobile_frm = null;
break;
case "中国联通":
Unicom_frm.Dispose();
Unicom_frm = null;
break;
case "中国电信":
Telecom_frm.Dispose();
Telecom_frm = null;
break;
case "联通固话":
objUnicomPhone.Dispose();
objUnicomPhone = null;
break;
case "电信固话":
objTelecomPhone.Dispose();
objTelecomPhone = null;
break;
case "全国缴费":
objNationalMobile.Dispose();
objNationalMobile = null;
break;
case "QQ币充值":
objQq.Dispose();
objQq = null;
break;
case "手机短信":
objSmsMain.Dispose();
objSmsMain = null;
break;
case "3G通充值":
objtranMain.Dispose();
objtranMain = null;
break;
case "体育彩票":
TLottery_frm.Dispose();
TLottery_frm = null;
break;
case "全国游戏":
objSNationalGame.Dispose();
objSNationalGame = null;
break;
case "火车票":
objTgFrm.Dispose();
objTgFrm = null;
break;
case "中国电力":
objPower.Dispose();
objPower = null;
break;
case "身体证查询":
objCheckIDCard.Dispose();
objCheckIDCard = null;
break;
default:
break;
}
GC.Collect();
}
不知道 这样好不好不过确定是内存占用少了很多现在基本不会过50MB,以前没有注意这块,现在给大家分享一下我的经验,也希望能给常用这两个控件并且没有注意到这个问题的朋友以帮助吧,如果我的方法有不到这处还希望大家提出建议或是解决方案我将不胜感激,对性能这块如果大家有什么经验的话也希望能分享一下,呵呵
addTabControl方法
/// <summary>
/// 添加一个选项卡
/// </summary>
/// <param name="MainTabControlKey">选项卡的键值</param>
/// <param name="MainTabControlName">选项卡要显示的名称</param>
/// <param name="objTabControl">要添加到的TabControl对象</param>
/// <param name="objfrm">要被添加到选项卡的用户控件对象</param>
private void addTabControl(string MainTabControlKey, string MainTabControlName, TabControl objTabControl, UserControl objfrm)
{
try
{
if (objTabControl.Controls.Contains(objTabControl.TabPages[MainTabControlName]) == false)
{
//声明新的TabPage对象tabpage
TabPage tabpage = new TabPage();
//选项卡的名称
tabpage.Text = MainTabControlName;
tabpage.Name = MainTabControlKey;
////添加tabPage标签图片
switch (tabpage.Text.ToString().Trim())
{
case "中国移动":
tabpage.ImageIndex = 1;
break;
case "中国联通":
tabpage.ImageIndex = 2;
break;
case "中国电信":
tabpage.ImageIndex = 3;
break;
case "信用卡还贷":
tabpage.ImageIndex = 4;
break;
case "生活缴费":
tabpage.ImageIndex = 5;
break;
case "游戏币充值":
tabpage.ImageIndex = 6;
break;
case "彩票卖场":
tabpage.ImageIndex = 7;
break;
case "机票订购":
tabpage.ImageIndex = 8;
break;
case "全国充值":
tabpage.ImageIndex = 9;
break;
case "联通固话":
tabpage.ImageIndex = 10;
break;
case "电信固话":
tabpage.ImageIndex = 10;
break;
case "体育彩票":
tabpage.ImageIndex = 11;
break;
case "福利彩票":
tabpage.ImageIndex = 12;
break;
case "QQ币充值":
tabpage.ImageIndex = 13;
break;
case "移动选号":
tabpage.ImageIndex = 1;
break;
case "联通选号":
tabpage.ImageIndex = 2;
break;
case "电信选号":
tabpage.ImageIndex = 3;
break;
default:
tabpage.ImageIndex = 5;
break;
}
//使得objfrm充满整个父窗体
objfrm.Dock = DockStyle.Fill;
//子窗体大小设置为选项卡大小
objfrm.Size = tabpage.Size;
//在tabpage中添加panel
tabpage.Controls.Add(objfrm);
tabpage.AutoScroll = true;
tabpage.AutoScrollMinSize = new Size(700, 500);
//Image m_Img = new Bitmap(Application.StartupPath + "\\images\\001.bmp");
//if (m_Img != null)
//{
// Point pt = tabpage.AutoScrollPosition;
// e.DrawImage(m_Img, pt.X, pt.Y, m_Img.Width, m_Img.Height);
//}
//添加tabpage
objTabControl.Controls.Add(tabpage);
//使得tabpage为选中状态
objTabControl.SelectedTab = tabpage;
}
else
{
//设为当前选中的选项
objTabControl.SelectedTab = objTabControl.TabPages[MainTabControlName];
}
}
catch (Exception ex)
{
MessageBoxForm objm = new MessageBoxForm("添加选项卡时出错,请检查是否正确连接数据" + ex.Message.ToString());
objm.ShowDialog();
}
}