【问题标题】:C# : the close method of Xml.Load(file)C#:Xml.Load(file) 的关闭方法
【发布时间】:2012-06-16 11:23:49
【问题描述】:

我编写了一些代码,它使用XmlDocument 对象加载XML 文档,以便计算它的节点。方法如下:

XmlDocument xml = new XmlDocument();
xml.Load(textBox1.Text);
XmlNodeList nodes = xml.SelectNodes("//File");
foreach (XmlNode node in nodes)
{
    number_of_childs++;
}

我面临的问题是,当导入一个大文件时,它需要 700MB 的 RAM。如果我然后尝试对文件进行一些操作,或者甚至从中读取以在ListView 中显示其数据,则应用程序需要 2GB 的 RAM。所以,我想知道,是否有一种方法可以关闭 XmlDocument 并释放其内存,释放 RAM。就好像它忘记了从内存中删除它的内容。

【问题讨论】:

    标签: c# xml memory memory-management xmldocument


    【解决方案1】:

    没有。 XmlDocument 类没有实现IDisposable,所以没有办法强制它随意释放它的资源。如果您确实需要立即释放 XmlDocument 使用的内存,唯一的方法是执行以下操作:

    nodes = null;
    xml = null;
    GC.Collect();
    

    垃圾收集器在单独的线程上工作,因此它可能仍然不会立即发生。要强制垃圾收集同步发生,在继续执行代码之前,您还必须调用WaitForPendingFinalizers,如下所示:

    nodes = null;
    xml = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
    

    XmlDocument 总是将整个文档一次加载到内存中。如果您只是想以流的形式遍历文档中的节点,一次只加载一点,这就是 XmlReader 类的用途。但是,这样会失去很多功能。例如,无法通过 XPath 选择节点,就像您在示例中所做的那样。使用XmlReader,您必须编写自己的逻辑来确定您在文档中的位置以及是否与您要查找的内容相匹配。

    【讨论】:

    • 感谢您提供的信息,但它不起作用,我已经应用了您的代码,但它仍然保留了相同数量的内存。
    • 是的,它有效,但是应用程序的第二步是读取每个节点并将其输入到列表视图中,所以问题仍然存在,但是如果我可以读取 xml 的每个节点并释放它呢? s 成功存储在某处时的内存空间
    • 我的例子就是这样做的。如果释放用于加载 XML 的内存,但显然列表视图控件仍将使用内存来将数据存储在其列表项中。顺便说一句,您是否在内存使用方面遇到了严重的性能问题,或者您是否只是注意到内存在增加而只是打扰您的感受?如果这只是你的感受,你需要习惯于忽视它。由于 .NET 使用垃圾收集,因此您的应用程序的内存消耗会在各处看似随机波动。这是正常的和预期的。你不应该担心它
    • @R.Vector 哎呀。在我的示例中,我忘记将节点设置为 null。
    • 非常感谢@Steve,它确实有助于提高应用程序在内存使用方面的性能,在改进之前应用程序需要大约 2GB 或 RAM 并崩溃,但改进后只需要 1.4GB
    【解决方案2】:

    无需将您的对象设置为空。 GC 应该能够指示 Document 是否没有被自己进一步使用。这将在需要内存时自动发生,但如果您想立即清除它,请致电GC.Collect()。更多讨论请参见this thread

    【讨论】:

    • 我同意这通常不是一个大问题,GC 最终会自行释放内存,但如果您要手动调用垃圾收集器,则必须将变量设置为 null在调用 GC.Collect 之前,否则对象仍然会被引用,不会被回收。
    • @Steven Doggart,您的说法仅在 Debug 版本中是正确的。在 Release 版本中,设置为 null 不是必需的——GC 足够聪明,可以在不将其设置为 null 的情况下看到它不再被引用。例如,请参阅stackoverflow.com/questions/5545288/…
    • @MattSmith 这很令人惊讶和有趣。这是因为默认情况下,Release 版本包含额外的优化,一旦不再使用,它​​就会自动将变量设置为null,还是什么?
    • @StevenDoggart,我相信只是该变量在上次使用后被认为不再被引用。我不希望 Release 版本会添加将变量设置为 null 的代码。更重要的是,调试构建导致引用存在的时间比它自然允许在调试器中查看该变量的时间更长。
    • @StevenDoggart,这里是显示调试和发布之间不同顺序的示例应用程序:codepad.org/zmI3vBlQ
    【解决方案3】:

    如果您不必操作 XML,只需使用 XMLReader 读取 XML,这是单向且最快的,内存密集型操作较少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 2013-06-26
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 2019-01-26
      相关资源
      最近更新 更多