当前位置:编程学习 > C#/ASP.NET >>

C#服务程序内存控制问题

1、一个服务程序,每天定时执行一个任务。因此我在服务程序中增加了timer控件。每秒检查一次时间。
但是现在的问题是,还没有到指定时间,内存就在每秒8k的上升。
我启动服务后占用9M左右内存,启动后以8K/s的速度,一直增长到13~14M 就停止了不再增加了。
2、还有个问题,当到达指定时间后,调用Form1中的方法,执行任务。内存会提升到23M左右。任务结束后,这些提升上去的内存就没有被释放了。我在调用结束后。已经做过Dispose();工作了,还是没有释放。在Form1的任务中,我有使用Process调用过一些外部命令,但是在调用结束后都,判断过结束与否,并且全部close了。另外在Form1,中的静态变量,在程序结束时,string类,都设为 =null; 列表类,都做了如下操作
            listBox1.Items.Clear();
            listBox1.Dispose();
            GC.SuppressFinalize(listBox1);  
3、在执行一次任务后,再次回到等待状态时,内存就基本上稳定在23~24M了,没有像之前那样 8k/s 的速度增长了。到下一次执行任务是系统内存又增加了2M左右。目前就测试了两天,就增加到25M左右了,这样的速度时间长了以后就会占用很大内存。希望高手们帮忙看看是哪里的问题。谢谢大家了!!!
 

服务类中,时间监控部分代码
 
private void timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            timer1.Enabled = false;
            flag = TimeSpan.Parse(DateTime.Now.TimeOfDay.ToString().Substring(0, 8)).Equals(TimeSpan.Parse(actionTime));
            if (flag)
            {
                XmlOperate xo = new XmlOperate();//原来这个地方我是在程序初始化时设置成静态变量,后来为了节省内存改在这里在new出新对象,结束后在置空。
                xo.updateXmlDate("RunFlag", "1");
                Form1 fm = new Form1();();//原来这个地方我是在程序初始化时设置成静态变量,后来为了节省内存改在这里在new出新对象,调用结束后Dispose()。

                fm.begin();
                fm.Dispose();
                GC.SuppressFinalize(fm);

                xo.updateXmlDate("RunFlag", "0");
                xo = null;
            }            
            timer1.Enabled = true;            
        }


调用进程结束后的操作代码

 if (!p.WaitForExit(100))
   {
      log.writelog("调用外部命令的进程没有正常结束!");
   }
   else
   {
      log.writelog("调用外部命令的进程正常结束!");//在程序执行日志中,全部正常输出这一行了。
   }
  p.Close();
--------------------编程问答-------------------- up --------------------编程问答-------------------- 顶起&…… --------------------编程问答-------------------- 大家帮忙看看!
多谢!!! --------------------编程问答-------------------- 再顶。。。 --------------------编程问答-------------------- 1. 服务程序的内存使用模型,不是一成不变的。 应该是一种波浪形状
好的服务程序经过长时间内存检测,波峰要一致,波谷要一致。时间不管多长也不会造成溢出。
可以使用 .net memory profiler 类似这种工具进行检测

2. 要想程序健康,还是多依靠GC自动回收比较合理。不建议强制使用Dispose进行释放,或者GC强制释放。 

3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。




--------------------编程问答-------------------- 关注 --------------------编程问答--------------------
引用 5 楼 builderc 的回复:
1. 服务程序的内存使用模型,不是一成不变的。 应该是一种波浪形状
好的服务程序经过长时间内存检测,波峰要一致,波谷要一致。时间不管多长也不会造成溢出。
可以使用 .net memory profiler 类似这种工具进行检测

2. 要想程序健康,还是多依靠GC自动回收比较合理。不建议强制使用Dispose进行释放,或者GC强制释放。

3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。


补充一点,波峰不是精确到M的,可能误差在几M, 波谷的误差也不是精确到M, 也有可能误差在几M
重要的是长时间检测。波峰和波谷不是在缓慢上升,在一定误差内反复波动,也可判定程序内存使用可靠。

--------------------编程问答-------------------- 5楼的,高手,之前我也没有使用使用Dispose进行释放。就是因为有内存问题,怀疑是内存没有释放,才使用的。但是使用后没有什么效果。
“3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。 ”
很高兴您能提出一个建议!这方面小弟真是比较薄弱。可否进一步介绍一下,或者针对问题给一个简单的介绍。 --------------------编程问答-------------------- 大伙帮忙看看~ --------------------编程问答--------------------
引用 8 楼 feixiang19822008 的回复:
5楼的,高手,之前我也没有使用使用Dispose进行释放。就是因为有内存问题,怀疑是内存没有释放,才使用的。但是使用后没有什么效果。
“3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。 ”
很高兴您能提出一个建议!这方面小弟真是比较薄弱。可否进一步介绍一下,或者针对问题给一个简单的介绍。


public class MyResource: IDisposable
{

   ...
}

public class call
{
   using(MyResource res = new MyResource())
   {

   }
}
--------------------编程问答-------------------- 使用垃圾回收试试:GC.Collect(); --------------------编程问答-------------------- mark --------------------编程问答--------------------
引用 11 楼 mjp1234airen4385 的回复:
使用垃圾回收试试:GC.Collect();

这个试过了不行
--------------------编程问答--------------------
引用 10 楼 builderc 的回复:
引用 8 楼 feixiang19822008 的回复:
5楼的,高手,之前我也没有使用使用Dispose进行释放。就是因为有内存问题,怀疑是内存没有释放,才使用的。但是使用后没有什么效果。
“3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。 ”
很高兴您能提出一个建议!这方面小弟真是比较薄弱。可否进一步介绍一下,或者针对问题给一个简单的介绍。


C# codepublicclass MyResource: IDisposable
{

   ...
}publicclass call
{using(MyResource res=new MyResource())
   {

   }
}


不好意思,说实话,还是不是很明白到底怎么做。。。
您的意思是把原来的程序继承IDisposable?然后再新建一个类调用?
不太明白。。。 --------------------编程问答-------------------- 我把服务主方法的代码贴出来了,还希望大家再帮忙赐教一下!
我在msdn上也看到IDisposable..::.Dispose 方法 的示例了,但是自己才疏学浅,看了半天没太明白怎么用在我的程序中。
多谢了!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.Threading;

namespace FileMoveService
{
    public partial class FileMoveMain : ServiceBase
    {
        public FileMoveMain()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 每天开始执行移动文件工作的时间,采用24小时制
        /// </summary>
        private static string actionTime = "";
        /// <summary>
        /// 时间匹配标志
        /// </summary>
        private static bool flag = true;

        protected override void OnStart(string[] args)     
        {
            LogClass log = new LogClass();//日志类
            XmlOperate xo = new XmlOperate();//操作xml文件类
            CreateSymLink cs = new CreateSymLink();//创建符号链接类
            actionTime = xo.readXmlDate("ActionTime");
            xo.updateXmlDate("RunFlag", "0");
            if (cs.getWindowsVer() == 1)
            {
                cs.beginSenable();
            }
            Thread.Sleep(100);
            log.writelog("开启移动文件服务!    后台程序运行时间为每天:" + actionTime);
            cs = null;
            xo = null;
            log = null;
        }

        protected override void OnStop()
        {
            LogClass log = new LogClass();
            XmlOperate xo = new XmlOperate();
            CreateSymLink cs = new CreateSymLink();
            xo.updateXmlDate("RunFlag", "0");
            if (cs.getWindowsVer() == 1)
            {
                cs.stopSenable();
            }
            log.writelog("关闭移动文件服务");
            cs = null;
            xo = null;
            log = null;
        }
        private void timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            timer1.Enabled = false;
            flag = TimeSpan.Parse(DateTime.Now.TimeOfDay.ToString().Substring(0, 8)).Equals(TimeSpan.Parse(actionTime));
            if (flag)
            {
                XmlOperate xo = new XmlOperate();
                xo.updateXmlDate("RunFlag", "1");
                Form1 fm = new Form1();
                fm.begin();
                fm.Dispose();
                GC.SuppressFinalize(fm);
                //GC.Collect();
                xo.updateXmlDate("RunFlag", "0");
                xo = null;
            }            
            timer1.Enabled = true;
            
        }

    }
}

--------------------编程问答--------------------
引用 14 楼 feixiang19822008 的回复:
引用 10 楼 builderc 的回复:
引用 8 楼 feixiang19822008 的回复:
5楼的,高手,之前我也没有使用使用Dispose进行释放。就是因为有内存问题,怀疑是内存没有释放,才使用的。但是使用后没有什么效果。
“3. 鼓励使用继承了 IDispose 的对象,并使用 using(){} 进行调用。 ”
很高兴您能提出一个建议!这方面小弟真是比较薄弱。可否进一步介绍一下,或者针对问题给一个简单的介绍。


C# codepublicclass MyResource: IDisposable
{

  ...
}publicclass call
{using(MyResource res=new MyResource())
  {

  }
}


不好意思,说实话,还是不是很明白到底怎么做。。。
您的意思是把原来的程序继承IDisposable?然后再新建一个类调用?
不太明白。。。


就是自己创造的类、对象尽量继承IDisposable,按照系统标准 写上 Dispose 函数。
使用的时候不要直接调用Dispose, 使用Using(){} 系统会自动调用。 --------------------编程问答-------------------- 哦,好像明白一些了
我正在按照您的方法,再参照MSDN的例子做。
但是在MSDN中是把类重写了构造方法,加了句柄参数

如:
        // The class constructor.
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }


这个有必要吗?
如果是必要的,那么我在调用它的时候怎么传这个参数呀?

public class call
{
   using(MyResource res = new MyResource())//这里怎么传句柄参数?
   {

   }
}



--------------------编程问答-------------------- 还有高手能帮帮忙吗?
--------------------编程问答-------------------- 顶起来! --------------------编程问答-------------------- 顶不起了。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,