2011-05-01 78 views
3

我有一些C#代码,它读取巨大的文件,经过一些操作后,将其引用设置为null并退出函数,但内存不会释放。即使退出函数后,.NET内存也不能释放

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(xmlString); 
XmlService.ConvertExcelToXML(xmlDoc); 
int sdfid = 320; 
XmlService.CompareXML(xmlDoc, ref sdfid, pkid); 
xmlDoc.RemoveAll(); 
xmlDoc = null; 

xmlDoc是一个非常大的字符串,通常大约50 MB。当我退出该功能时,该内存被永久占用,而且我必须每天重新启动我的服务几次,否则内存使用量将达到1GB。

我试图使用GC.Collect,但没有用。

预先感谢您。

编辑

这里是XmlService的类声明。它没有变数。所有的方法都是静态的

public class XmlService 

ConvertExcelToXML函数的代码

public static bool ConvertExcelToXML(XmlDocument xmlDoc) { 
     XmlNamespaceManager nm = new XmlNamespaceManager(xmlDoc.NameTable); 
     nm.AddNamespace("z", "urn:schemas-microsoft-com:office:spreadsheet"); 
     nm.AddNamespace("o", "urn:schemas-microsoft-com:office:office"); 
     nm.AddNamespace("x", "urn:schemas-microsoft-com:office:excel"); 
     nm.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet"); 
     nm.AddNamespace("html", "http://www.w3.org/TR/REC-html40"); 
     XmlNodeList rows = xmlDoc.DocumentElement.SelectNodes("//z:Worksheet/z:Table/z:Row", nm); 
     if (rows != null && rows.Count > 0) 
     { 
      XmlNode nodeNames = rows[0]; 
      XmlNode nodeValues = rows[1]; 

      XmlNode destRootNode = xmlDoc.CreateNode(XmlNodeType.Element, "ParentNode", null); 
      XmlNode fieldNode = null; 
      XmlNode dataNode = null; 
       for (int i = 0; i < nodeNames.ChildNodes.Count; i++) 
       { 
        if (nodeNames.ChildNodes[i].HasChildNodes) 
        { 
         string nodeName = nodeNames.ChildNodes[i].ChildNodes[0].InnerXml; 
         //string nodeValue = nodeValues.ChildNodes[i].ChildNodes[0].InnerXml; 
         string nodeValue = "DataField" + i.ToString(); 

         fieldNode = xmlDoc.CreateNode(XmlNodeType.Element, "Field", null); 
         dataNode = xmlDoc.CreateNode(XmlNodeType.Element, "Data", null); 
         dataNode.InnerXml = nodeName; 
         fieldNode.AppendChild(dataNode); 
         destRootNode.AppendChild(fieldNode); 

         fieldNode = xmlDoc.CreateNode(XmlNodeType.Element, "Field", null); 
         dataNode = xmlDoc.CreateNode(XmlNodeType.Element, "Data", null); 
         dataNode.InnerXml = nodeValue; 
         fieldNode.AppendChild(dataNode); 
         destRootNode.AppendChild(fieldNode); 
        } 
       } 
      xmlDoc.LoadXml("<ParentNode>" + destRootNode.InnerXml + "</ParentNode>"); 
      return true; 
      } 
      return false; 

} 

和规范CompareXML

 public static void CompareXML(XmlDocument filexmlDoc, ref int maxSDFID, string PKID) 
    { 
     FieldsListBO tmpFieldListBO = null; 

     ResponseDTO responseDTO = DbService.getConnection(); 
     DbConnection con = (DbConnection)responseDTO.ReturnedObjects[Constants.CONNECTION_OBJECT]; 
     DbProviderFactory factory = (DbProviderFactory)responseDTO.ReturnedObjects[Constants.FACTORY_OBJECT]; 
     DbCommand cmd = factory.CreateCommand(); 

     cmd.CommandText = "select * from tree_store"; 
     cmd.Connection = con; 
     con.Open(); 

     DbDataReader dr = cmd.ExecuteReader(); 
     dr.Read(); 
     String pXmlizedString = (String)dr["TransactionTree"]; 
     dr.Dispose(); 
     cmd.Dispose(); 
     con.Dispose(); 
     XmlSerializer xs = new XmlSerializer(typeof(FieldsListBO)); 
     MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString)); 
     XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.ASCII); 
     tmpFieldListBO = (FieldsListBO)xs.Deserialize(memoryStream); 
     memoryStream.Dispose(); 
     xmlTextWriter.Close(); 
     if (tmpFieldListBO.FieldsList.Count < 1) 
     { 
      maxSDFID = 0; 
      return; 
     } 

     FieldsListBO fieldListBO = new FieldsListBO(); 

     for (int i = 0; i < tmpFieldListBO.FieldsList.Count; i++) 
     { 
      if (tmpFieldListBO.FieldsList[i]._pkid.Equals(PKID)) 
      { 
       fieldListBO.FieldsList.Add(tmpFieldListBO.FieldsList[i]); 
      } 
     } 

     GetMaxSDFID(filexmlDoc, ref maxSDFID, fieldListBO); 
    } 

filexmlDoc传递给GetMaxSDFID只是被transversed由节点节点没有更新/ delation完成

+1

发布了XmlService.ConvertExcelToXML和XmlService.CompareXML的代码 – 2011-05-01 07:39:15

+2

我怀疑问题出在'XmlService'方法 - 它有没有可能是不安全/非托管代码?另一个选择是它使用'static'变量,从而将它保存在内存中。 – 2011-05-01 07:40:04

+0

你确定这段代码导致了这个问题吗?如何完成Excel转换?或者在CompareXML方法中做了什么。 – ChristiaanV 2011-05-01 07:40:07

回答

2

我们需要知道XmlService在ord中的作用呃更多地了解正在发生的事情。它可以很容易地存储数据出于某种原因(或者除了糟糕的设计之外可能没有理由)。

假设该方法在您向我们展示的代码后不久就结束,那么您绝对不需要将此变量设置为null,并且如果XmlService未持有对该对象的引用,那么您不需要请致电RemoveAll

请注意,XmlDocument对象本身不会很大,虽然它的对象图可能是。 xmlString本身可能虽然大 - 如果最终在大型对象堆中有很多对象,那可能会给您带来问题,因为即使空间被释放后LOH也不会被压缩。尽管如此,我不会期望它表现得像这样。

您是否有将XML转换为字符串变量以开始?您可以将它流式传输(例如从文件中)吗?

+0

奥斯威戈湖高? – corlettk 2011-05-01 07:45:28

+0

大对象堆:) - 用于超过80K大小的对象 – 2011-05-01 07:48:30

4

我很抱歉地说,我可能是错的,但它真的看起来就像你猜测问题的根源。

我说这是因为你试图做的。取消一个局部变量并调用GC.Collect,希望这能解决它。有经验的人会告诉你,这不是,也无济于事。

猜测通常是一种很好的方法(例如其他人猜测XmlService.ConvertExcelToXML可能是一个问题),但为什么猜你什么时候不需要,当你的应用程序消耗了大量的记忆。您可以使用ProcDump,但还有很多其他方法可以执行此操作。

安装WinDbg。使用此工具,您可以使用​​等命令分析您的内存转储,这些命令可以准确告诉您1 GB的位置。