猿问

使用StreamReader和XmlSeriizer的内存泄漏

使用StreamReader和XmlSeriizer的内存泄漏

我已经在谷歌搜索了几个小时,尝试了不同的东西,但似乎无法做到这一点.

当我运行这段代码时,内存使用量不断增加。

while (true){
    try
    {
        foreach (string sym in stringlist)
        {
            StreamReader r = new StreamReader(@"C:\Program Files\" + sym + ".xml");
            XmlSerializer xml = new XmlSerializer(typeof(XMLObj), new XmlRootAttribute("rootNode"));
            XMLObj obj = (XMLObj)xml.Deserialize(r);                       
            obj.Dispose();
            r.Dispose();
            r.Close();
        }
    }    
    catch(Exception ex) 
    {
        Console.WriteLine(ex.ToString()); 
    }
    Thread.Sleep(1000);
    Console.Clear();
}

XMLObj是一个自定义对象。

[Serializable()]public class XMLObj: IDisposable{
    [XmlElement("block")]
    public List<XMLnode> nodes{ get; set; }

    public XMLObj() { }

    public void Dispose()
    {
        nodes.ForEach(n => n.Dispose());
        nodes= null;

        GC.SuppressFinalize(this);
    }}

我尝试过添加GC.Colect(),但这似乎没有任何作用。


繁花不似锦
浏览 561回答 3
3回答

慕标5832272

漏洞在这里:new&nbsp;XmlSerializer(typeof(XMLObj),&nbsp;new&nbsp;XmlRootAttribute("rootNode"))XmlSerializer使用程序集生成,无法收集程序集。它为最简单构造器场景(new XmlSerializer(Type)等),但不在这种情况下。因此,您应该手动缓存它:static&nbsp;readonly&nbsp;XmlSerializer&nbsp;mySerializer&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;XmlSerializer(typeof(XMLObj),&nbsp;new&nbsp;XmlRootAttribute("rootNode"))并使用缓存的序列化程序实例。

慕尼黑5688855

首先,即使抛出异常(XMLObj也是如此),您也应该处理StreamReader。使用using声明。当前,当抛出异常时,您将不会释放。你不太可能有内存泄漏。更有可能的是,运行时还没有选择收集内存。甚至GC.Colect也不一定会导致内存释放。在处理非常大的XML文件(多GB)时,我遇到了类似的情况。尽管运行时占用了大部分可用内存,但在内存压力需要时,它也会释放它。您可以使用VisualStudio中的内存分析器来查看分配了什么内存,以及它驻留在哪一代中。更新“凯伊辛格”的评论值得调查。它表示XmlSeriizer可能正在为每个循环迭代创建一个新的缓存对象定义。XMLSeriizer构造函数使用反射为要序列化的类型创建临时程序集,而且由于代码生成开销很大,因此程序集按每种类型缓存在内存中。但是很多时候,根名称将被更改,并且可以是动态的,并且它不会缓存动态程序集。因此,每当调用上面的代码行时,它每次都会加载新的程序集,并将一直驻留在内存中,直到卸载AppDomain为止。
随时随地看视频慕课网APP
我要回答