使用CLR会造成内存方面的问题吗

http://tech.ddvip.com   2008年01月23日    社区交流

内容摘要:我老是担心使用CLR会造成内存方面的问题,比如内存不能回收。其实想一想也许我过滤了,毕竟.NET Framework能够自己回收托管内存。既然在应用服务器上能使用,数据库上似乎也可以使用。

  我老是担心使用CLR会造成内存方面的问题,比如内存不能回收。其实想一想也许我过滤了,毕竟.NET Framework能够自己回收托管内存。既然在应用服务器上能使用,数据库上似乎也可以使用。

  希望听一听大家的经验和见解~~

  Peak Wong:

  一般不用, 主要是DBA管理这种东西的时候会很麻烦, 因为自己写的CLR很难保证没有BUG, 一旦出BUG, 如果只是影响调用那一部分还好, 如果导致整个服务挂掉, 则很危险了(而且往往导致服务器挂掉还不一定查得出来是否CLR的问题)

  另外, 部署和迁移也是要考虑的问题之一。还有感觉 CLR 还没有想像中的那么稳定(或者是与 SQL SERVER 的配合没有想像中的好)

  例如在处理 复制出错的时候, 有时会调用一些存储过程去查看出错相关的信息, 这些存储过程中的一部分就是 CLR 存储过程, 经常会发现怎么也调不成功, 说什么内存错误什么的, 但实际上空闲内存肯定是够的.

  而且一般第一次调用CLR的时候, 加载程序集花费的时间也不短, 所以如果 CLR 用得多, 内存又不太够, 导致一些CLR程序集老是反复加载的话, 性能会非常低。

  内存回收机制确实很智能,只不过只需要把比如打开文件啊,开数据库啊什么的关闭就可以了。就不会造成多余的系统开销。如果害怕的话,可以写段折构函数!以前学习的时候写过一个例子,但是用处不打,可以借鉴一下。

  C# code

using System;
using System.IO;
using System.Windows.Forms;
  
namespace nameSpace1
{
  public class gcDemo:IDisposable
  {
  static int ctor_cnt = 0;
    static int dtor_cnt = 0;
  static public gcDemo c1;
  static public StreamWriter ofile;
  static int iterations;
  private bool isDispose = false;
  public void Dispose()
    {
      Dispose(true);
      System.GC.SuppressFinalize(this);
    }
  protected virtual void Dispose(bool disposing)
    {
      if(!isDispose)
      {
        if(disposing)
          ofile.Close();
      }
      isDispose = true;
    }
  static public int Iterations
    {
      get
      {
        return iterations;
      }
      set
      {
        iterations = value;
      }
    }
  static gcDemo()
    {
      string startupPath;
  startupPath = Application.StartupPath;
  ofile = new StreamWriter(new FileStream(startupPath+@"fx.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None));
  ofile.WriteLine("all trace output at {0}", startupPath+@"fx.txt");
    
  Console.WriteLine("startupPath is :{0}", startupPath);
    }
    public gcDemo()
    {
      ofile.WriteLine("gcDemo Class Constructor: {0}", ++ctor_cnt);
      ofile.Flush();
    }
    
    ~gcDemo()
    {
      try
      {
        ofile.WriteLine("gcDemo Class Destructor: {0}", ++dtor_cnt);
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      Dispose(false);
  
    }
  static public void gcObject()
    {
      for(int ix = 0;ix<gcDemo.Iterations;ix++)
        c1 = new gcDemo();
  
    }
  }
  class EntryPoint
  {
  public static void testM()
    {
      gcDemo.Iterations = 100;
      gcDemo.gcObject();
  }
    static void Main()
    {
  testM();
      gcDemo.c1.Dispose();
  try
      {
        gcDemo.ofile.WriteLine("test");
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
  System.Threading.Thread.Sleep(3000);
  
    }
  }
}

  在上面的例子中看出,折构函数~gcDemo的特性为,系统能够确保非托管代码在程序执行后能够得到回收。因为原理是~gcDemo的代码被封装在Finalize()方法的一个try块内。并且把该方法调用放在finally中,由此确保了它的执行,但是缺点是,是在程序执行完毕后进行删除对象需要处理两次才行,第一次不处理,第二次删除,由此可能对系统效率产生很大的影响。

  比如我在~gcDemo程序中加入的

来源:IT专家网    作者:Peak Wong    责编:豆豆技术应用

正在加载评论...