http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 11602|回复: 12

[学习交流] WinForm中DataGridView存在漏内存情况

[复制链接]
发表于 2014-5-12 11:15:32 | 显示全部楼层 |阅读模式
    最近公司在开发一个TCP接口程序,因为涉及到连接多个服务端,因此是多线程并行处理,所以我就想做个逻辑线程状态列表,方便查看线程内部的运行情况。
   我的开发思路是内个线程中创建一个事件,通过事件的方式把当前线程中的最新运行状态输出到主界面进行显示,主线程中有个线程信息列表。子线程触发状态改变后,通过事件将当前状态通知到主线程,主线程根据子线程提供的最新状态更新到线程信息列表中,最后读取线程信息列表生成一个DataTable,将DataTable赋给DataGridView的 DataSource 属性,具体实现函数如下:
   
[C#] 纯文本查看 复制代码
/// <summary>
        /// 操作DataGridView控件,增加文本框信息
        /// </summary>
        /// <param name="conl">DataGridView控件名称</param>
        /// <param name="loglevel">日志等级</param>
        /// <param name="msg">日志信息</param>
        private void SetDataGridView(DataGridView conl, DataTable dt_para)
        {

            if (conl.InvokeRequired)
            {
                CommdDataGridDelegate dl = new CommdDataGridDelegate(SetDataGridView);
                conl.Invoke(dl, conl, dt_para);
            } // 异步调用委托,调用后立即返回并立即执行下面的语句
            else
            {
                DataTable dt = (DataTable)conl.DataSource;
                conl.DataSource = dt_para;
                if (dt != null)
                {
                    dt.Clear();

                    dt.Dispose();
                    dt = null;
                }
            }
        }



就是这样一段代码,我左看右看,我都将它 clear(),Dispose(),还将它指向Null了,为何还会造成对象不能被回收呢?用了很多内存检测工具也看不出个所以然,大家一起看看,讨论讨论






1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
 楼主| 发表于 2014-5-12 11:16:12 | 显示全部楼层
这块我真不懂,还望大家指教
发表于 2014-5-12 14:15:04 | 显示全部楼层
 楼主| 发表于 2014-5-12 14:18:29 | 显示全部楼层
站长苏飞 发表于 2014-5-12 14:15
http://www.sufeinet.com/thread-13-1-1.html

我这个是winform 的,问题是我已经解决掉了,通过清空items里面的数据项,再一个一个的添加进去就不会有泄露的问题了,关键在于我想知道,为什么dispose掉了内存还会不停的涨呢?
发表于 2014-5-12 14:25:41 | 显示全部楼层
dt本身就是一个内部变量,你不用做任何操作也是会回收的,问题是你的dt_para和conl是怎么产生的,会不会因为这个造成的,或者是还有其他地方,你是怎么这么确定是dt呢,如果安你写的代码是dt的问题,那只能说明,是微软的C#言语出个问题,而且这个问题是域名变量不会释放的低级的不能再低级的错误,我宁可相信这世界上有鬼也不会相信这是真的,
 楼主| 发表于 2014-5-12 14:36:14 | 显示全部楼层
[C#] 纯文本查看 复制代码
/// <summary>
        /// 操作DataGridView控件,增加文本框信息
        /// </summary>
        /// <param name="conl">DataGridView控件名称</param>
        /// <param name="loglevel">日志等级</param>
        /// <param name="msg">日志信息</param>
        private void SetDataGridView(DataGridView conl, Dictionary<ushort, ThreadInfo> InfoList_para)
        {

            if (conl.InvokeRequired)
            {
                DataGridDelegate dl = new DataGridDelegate(SetDataGridView);
                conl.Invoke(dl, conl, InfoList_para);
            } // 异步调用委托,调用后立即返回并立即执行下面的语句
            else
            {
                
                conl.Rows.Clear();
                foreach (ThreadInfo tmpinfo in InfoList_para.Values)
                {
                    //conl.Rows.Add(tmpdr);
                    conl.Rows.Add(tmpinfo.Threadid, tmpinfo.Threadname, tmpinfo.Cid, tmpinfo.Starttime, getFormatTime(tmpinfo.TickCount), tmpinfo.Status, tmpinfo.Comm, tmpinfo.Lasttime);
                }
                
            }
        }




这个是我改正以后的代码,这个就不会出现内存泄露的问题,再一个DataTable是一个引用型变量,它取自于DataGridView的DataSource,不是局部变量。
你如果觉得不可能我可以把代码打包传上来的。最后问一下,加群是怎么加的?我已经申请了,迟迟不见验证通过或者拒绝

 楼主| 发表于 2014-5-12 14:43:10 | 显示全部楼层
zeng1988821 发表于 2014-5-12 14:18
我这个是winform 的,问题是我已经解决掉了,通过清空items里面的数据项,再一个一个的添加进去就不会有 ...

[C#] 纯文本查看 复制代码
/// <summary>
        /// 操作DataGridView控件,增加文本框信息
        /// </summary>
        /// <param name="conl">DataGridView控件名称</param>
        /// <param name="loglevel">日志等级</param>
        /// <param name="msg">日志信息</param>
        private void SetDataGridView(DataGridView conl, Dictionary<ushort, ThreadInfo> InfoList_para)
        {

            if (conl.InvokeRequired)
            {
                DataGridDelegate dl = new DataGridDelegate(SetDataGridView);
                conl.Invoke(dl, conl, InfoList_para);
            } // 异步调用委托,调用后立即返回并立即执行下面的语句
            else
            {
                 
                conl.Rows.Clear();
                foreach (ThreadInfo tmpinfo in InfoList_para.Values)
                {
                    //conl.Rows.Add(tmpdr);
                    conl.Rows.Add(tmpinfo.Threadid, tmpinfo.Threadname, tmpinfo.Cid, tmpinfo.Starttime, getFormatTime(tmpinfo.TickCount), tmpinfo.Status, tmpinfo.Comm, tmpinfo.Lasttime);
                }
                 
            }
        }




这个是我改正以后的代码,这个就不会出现内存泄露的问题,再一个DataTable是一个引用型变量,它取自于DataGridView的DataSource,不是局部变量。
你如果觉得不可能我可以把代码打包传上来的。最后问一下,加群是怎么加的?我已经申请了,迟迟不见验证通过或者拒绝
发表于 2014-5-12 14:46:11 | 显示全部楼层
conl.Rows.Clear();你加了这个,说明是conl影响的内存,和DT有什么关系呢,你一直Null 清空Dt干什么,这不是还是我上面说的吗,肯定不是DT问题。 一直没看到你的申请,你是不是以后加过被T了,被T过的,是不会再允许加的。或者是看错群号了。
 楼主| 发表于 2014-5-12 15:07:19 | 显示全部楼层
站长苏飞 发表于 2014-5-12 14:46
conl.Rows.Clear();你加了这个,说明是conl影响的内存,和DT有什么关系呢,你一直Null 清空Dt干什么,这不 ...

是这样的,我一开始的时候就用一个函数生成一个DataTable,直接赋值到DataSource上面去做数据更新的。后面的一个方法是我优化以后的方法用conl.Rows.Clear();。
前面用DataTable赋值的方法会出现内存泄露,后面一种不会泄露。
再来说一下前面方法中的问题:我的理解是每次生成的DataTable没有被回收,但是我的DataSource指向又是知道新的实例上去。按照内存回收的原理,将原实例进行Dispose和指向Null,是会被回收的。
我是将这两种方法做了比对的,同时开起来用赋值方法的内存只涨不跌,用conl.Rows.Clear();的又涨又跌,内存保持基本稳定。
如果让你来做这样的一个功能,用DataTable方法来更新你怎么操作呢?不用写代码,说点思路就行。
我今天才注册的论坛,肯定没有加过你的群。我看到你的加群说明贴中说是要加你QQ经过你提问验证才能加群的。可加你QQ你没回复任何信息。所以在这里问一下。
发表于 2014-5-12 15:13:52 | 显示全部楼层
zeng1988821 发表于 2014-5-12 15:07
是这样的,我一开始的时候就用一个函数生成一个DataTable,直接赋值到DataSource上面去做数据更新的。后 ...

不用问我,直接加就行了,确实没收到通知,这个具体是什么影响不了解也许 是QQ的Bug,我给你发的例子里的情况应该是一样的吧,我是在里面用的访问网站,如果你要释放可以使用Using语句试试。
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-11-22 20:23

© 2014-2021

快速回复 返回顶部 返回列表