.NET内存即使在退出该功能后也无法释放

时间:2011-05-01 07:33:58

标签: c# .net

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

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);
    }

传递给GetMaxSDFID的filexmlDoc只是逐个节点地被横向移动而没有更新/放弃

2 个答案:

答案 0 :(得分:4)

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

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

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

安装WinDbg。使用此工具,您可以使用!dumpheap –stat之类的命令分析内存转储,这些命令可以准确地告诉您1 GB的去向。

答案 1 :(得分:2)

我们需要知道XmlService做了什么,以便更多地了解正在发生的事情。它可以很容易地存储数据由于某种原因(或者除了糟糕的设计之外没有其他原因)。

假设方法在你向我们展示的代码之后不久结束,你绝对不需要将变量设置为null,如果XmlService没有持有对象的引用,你就不应该'我需要调用RemoveAll

请注意,XmlDocument对象本身不会很大,尽管它的对象图可能是。 xmlString本身可能很大 - 如果你最终在大对象堆上有很多对象,这可能会给你造成问题,因为即使在LOH没有压缩之后空间被释放。我不希望它表现得像这样。

将XML变成字符串变量吗?你可以流式传输它(例如从文件中传输)吗?