我有一些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只是逐个节点地被横向移动而没有更新/放弃
答案 0 :(得分:4)
我很抱歉这样说,我可能是错的,但真的看起来就像你猜测问题的根源一样。
我说这是因为你试图做的事情。取消一个局部变量并调用GC.Collect希望这将解决它。有经验的人会告诉你这不是它,也无济于事。
猜测通常是一种很好的方法(例如,其他人已经猜到XmlService.ConvertExcelToXML
可能是一个问题),但为什么当你不需要时猜测,当你的应用程序消耗了一个内存转储时大量的记忆。您可以使用ProcDump,但还有很多其他方法可以执行此操作。
安装WinDbg。使用此工具,您可以使用!dumpheap –stat
之类的命令分析内存转储,这些命令可以准确地告诉您1 GB的去向。
答案 1 :(得分:2)
我们需要知道XmlService
做了什么,以便更多地了解正在发生的事情。它可以很容易地存储数据由于某种原因(或者除了糟糕的设计之外没有其他原因)。
假设方法在你向我们展示的代码之后不久结束,你绝对不需要将变量设置为null,如果XmlService
没有持有对象的引用,你就不应该'我需要调用RemoveAll
。
请注意,XmlDocument
对象本身不会很大,尽管它的对象图可能是。 xmlString
本身可能很大 - 如果你最终在大对象堆上有很多对象,这可能会给你造成问题,因为即使在LOH没有压缩之后空间被释放。我不希望它表现得像这样。
你有将XML变成字符串变量吗?你可以流式传输它(例如从文件中传输)吗?