[已解决问题] 寻找 内存泄漏的解决办法
提问时间: 2008-09-04 23:34
悬赏分:50 浏览:535 次

最近发现写得一个服务程序,内存泄露,使得程序不能够7*18小时的运行(晚上0-6点)。

 

为了解决这个问题,想到了3个办法,请 各位老大帮忙说下可行性:

1:把所有的类都继承IDispose(),并实现资源释放,所有创建的对象都及时设置为null(这个不太能够实现,业务代码很多,使用的线程,事件等等很多,不太可能逐行的查看代码)

2:在写个服务程序,定时重启服务。(这个虽然能够重启服务,但是,占用的内存好像还是不能够一下子释放完)

3:修改原有服务程序,把原有服务程序 的业务代码等,全部放到一个AppDomain里面,定时检查这个AppDomain,并自动释放和创建。(不知道这个方法可以不 ,跪求这样的代码)

 

 

也跪求工具,用来查看内存被那些线程,对象等占用。。。

提问者:颜昌钢 - 初学一级

问题补充:程序没有递归,同时,也没有调用非托管组件,也没有静态字段。。。

就是线程比较多。。。但是,线程也没有被阻塞的情况。。。。

程序里面,事件用的比较多。。。

主要是 有的地方,事件的 -= 不太能够实现。。。

看来,个人感觉,可以用 AppDomain来加载业务代码,然后,可以在一定的时间后,卸载 AppDomain,然后再创建一个,但是,不知道 主要做是不是可以,同时,没有这样的代码,呵呵,所以,希望大家能够帮忙提供一下。。。。

当然,我也知道最好的办法是把梳理一下程序流程,并释放对象等,但是,由于时间紧,不太好一下完成这工作量

现在程序每天内存占用增加30M左右。。。。。。

所有回答(6)

所有的类都实现IDisponse并不是个好办法,修改工作量太大了,要显式调用Disponse方法才能释放。

要是重启服务一下都不能释放完的话,是不是线程非后台线程?所以,程序关闭,而线程还在运行。

一般内存占用不释放有几个原因:

1、递归,在递归方法中使用大对象,会造成大对象来不及回收;

2、非托管组件,非托管组件需要自己释放;

3、静态字段;

4、线程驻留,一般是被阻塞了


3个月前   回答者:Birdshover - 菜鸟二级

 

彻底解决办法还是要查出内存泄漏的原因。

建议用 .NET Memory Profiler 这个工具来跟踪内存使用情况

 

http://www.cnblogs.com/eaglet/archive/2008/09/05/1285169.html

 


3个月前   回答者:eaglet - 老鸟四级

不要经常创建对象,尽可能的缓存一个对象的副本


3个月前   回答者:lexus - 初学一级

CLR Profiler 可以给出详细的信息


3个月前   回答者:winzheng - 菜鸟二级

1:把所有的类都继承IDispose(),并实现资源释放,所有创建的对象都及时设置为null(这个不太能够实现,业务代码很多,使用的线程,事件等等很多,不太可能逐行的查看代码)

    如你所言,不太能够实现,只能督促自己,以后的项目一定要养成使用 using(something) 的好习惯,防止漏网之鱼。指导意义极大。

2:在写个服务程序,定时重启服务。(这个虽然能够重启服务,但是,占用的内存好像还是不能够一下子释放完)

    以前和同事也谈过这个,就是定时 kill 某个“进程”,然后启动该程序。模仿人的“关闭”、“启动”行为。我不知道你说的“内容无法释放”是什么意思,"进程"都杀掉了,还能站着茅坑?

3:修改原有服务程序,把原有服务程序 的业务代码等,全部放到一个AppDomain里面,定时检查这个AppDomain,并自动释放和创建。(不知道这个方法可以不 ,跪求这样的代码)

    能力不及,看着头晕。会不会是方案 2 的翻版?只不过增加了内存占用等检查措施,而不是一味的“猛杀猛起"。我见过通过 c# 启动 exe 等可执行文件的方法,包括杀死某个进程等。只要方向正确、坚定,手段我看不成问题,google 一下定能搞定!


3个月前   回答者:陛下 - 老鸟四级

第一感觉可能是事件导致的。  

 


3个月前   回答者:玉开 - 大侠五级
评论
3个月前   颜昌钢 :
我也认为大概是事件引起的。。。
也就是 这篇文章说的原因:
http://www.cnblogs.com/anders06/archive/2008/01/15/1040123.html

比如有如下的代码:
public delegate void TestDelegate(string strTest);
public Class Test
{
public event TestDelegate TestDelegate;

protected void OnTestDelegate(string strTest)
{
if(TestDelegate!=null)
{
TestDelegate(strTest);
}
}

public void AddStr(string strTest)
{
OnTestDelegate(strTest);
}
}

public Class Test1
{
public void MethodTest()
{
Test test= new Test();
test.TestDelegate+=new TestDelegate(Test_TestDelegate);
test.AddStr("1");
}
void Test_TestDelegate(string strTest)
{
//ToDo:
}
}

请问,如上的怎么实现 test.TestDelegate-=new TestDelegate(Test_TestDelegate);
3个月前   颜昌钢 :
TO:陛下:

2:在写个服务程序,定时重启服务。(这个虽然能够重启服务,但是,占用的内存好像还是不能够一下子释放完)

以前和同事也谈过这个,就是定时 kill 某个“进程”,然后启动该程序。模仿人的“关闭”、“启动”行为。我不知道你说的“内容无法释放”是什么意思,"进程"都杀掉了,还能站着茅坑?


我现在的情况是,在管理工具->服务 里面,选中当前服务,重新启动,内存还是那么大,根本就没有把内存释放。。。(也许我没有在OnStop这个函数里面释放完所有的资源吧。。。。。)

对于第三种,我有查看下MSDN上对于AppDomain的说明,其中有句话:

使用应用程序域隔离可能终止进程的任务。如果正在执行任务的 AppDomain 的状态变得不稳定,则可以卸载 AppDomain,但不会影响进程。当进程必须不重新启动而长时间运行时,这一点很重要。还可使用应用程序域隔离不应共享数据的任务。

似乎可以达到 把所有的业务代码都放到一个AppDomain里面,然后,当内存占用过多,在释放这个AppDomain,然后,再次创建一个。。。。。

3个月前   陛下 :
有一句成语:“积重难返”,相信兄弟肯定深有感触!
3个月前   颜昌钢 :

看来只有自己慢慢的花时间,把代码全部过一遍了。。。。。


   您需要登录以后才能回答!
 

我要提问

我的问题


快到期问题



> 问题排行榜

相关内容

相关链接