【问题标题】:c# serialization xmlwriter stringwriter out of memory for large objecthelpc# serialization xmlwriter stringwriter out memory for large objecthelp
【发布时间】:2016-10-18 07:10:27
【问题描述】:

我正在管理一个大型项目,需要以 xml 格式序列化和发送对象。该对象约为 130 mb。

(注意:我没有写这个项目,所以在这个方法之外进行编辑,或者彻底改变架构不是一种选择。它正常工作很好,但是当对象这么大时,它会抛出内存不足异常. 我需要用另一种方式来处理大物体。)

目前的代码是这样的:

public static string Serialize(object obj)
{
    string returnValue = null;

    if (null != obj)
    {
        System.Runtime.Serialization.DataContractSerializer formatter = new System.Runtime.Serialization.DataContractSerializer(obj.GetType());

        XDocument document = new XDocument();

        System.IO.StringWriter writer = new System.IO.StringWriter();
        System.Xml.XmlTextWriter xmlWriter = new XmlTextWriter(writer);

        formatter.WriteObject(xmlWriter, obj);
        xmlWriter.Close();

        returnValue = writer.ToString();
    }

    return returnValue;
}

它在 returnValue = writer.ToString() 处抛出内存不足异常。

我重写了它以使用我更喜欢的“使用”块:

public static string Serialize(object obj)
    {
        string returnValue = null;
        if (null != obj)
        {
            System.Runtime.Serialization.DataContractSerializer formatter = new System.Runtime.Serialization.DataContractSerializer(obj.GetType());
            using (System.IO.StringWriter writer = new System.IO.StringWriter())
            {
                using (System.Xml.XmlTextWriter xmlWriter = new XmlTextWriter(writer))
                {
                    formatter.WriteObject(xmlWriter, obj);
                    returnValue = writer.ToString();
                }
            }
        }
        return returnValue;
    }

对此进行研究,似乎 StringWriter 上的 ToString 方法实际上使用了两倍的 RAM。 (实际上我有很多可用的 RAM,超过 4 GB,所以我不确定为什么会出现内存不足错误)。

【问题讨论】:

  • 应用程序是为“x86”、“x64”还是“任何 CPU”构建的。如果构建平台是 x86,那么您的 .net 应用程序将作为 32 位进程运行,尽管您有 64 位环境并且如果它作为 x64 运行,则可以访问更多内存。
  • 这是 x86,我无法更改。但是,它仍然是一个 130 兆的对象,所以无论哪种方式,它都不会超过 x86 内存限制。
  • 在 32 位上,您可以分配多少 连续 内存的实际限制远小于 2GB 的理论限制。例如,请参阅stackoverflow.com/questions/2415434/…。您可以对此代码进行哪些更改?你必须返回一个字符串吗?会不会是别的?
  • 不要使用StringWriter。不要返回字符串。使用FileStream,直接写入即可。
  • 我经常看到类似这样的代码:大量的数据被序列化成一个字符串,然后这个字符串在方法之间反复传递。我的头发从它竖立起来! .NET 中的字符串是按值复制的。天啊!以垃圾收集器、CPU 周期和 John Skeet 的名义,把 g-string 留给女孩们!

标签: c# serialization out-of-memory xmltextwriter stringwriter


【解决方案1】:

好吧,我发现最好的解决方案是直接序列化到一个文件,然后我传递文件而不是传递一个字符串:

public static void Serialize(object obj, FileInfo destination)
{
    if (null != obj)
    {
        using (TextWriter writer = new StreamWriter(destination.FullName, false))
        {
            XmlTextWriter xmlWriter = null;
            try
            {
                xmlWriter = new XmlTextWriter(writer);
                DataContractSerializer formatter = new DataContractSerializer(obj.GetType());
                formatter.WriteObject(xmlWriter, obj);
            }
            finally
            {
                if (xmlWriter != null)
                {
                    xmlWriter.Flush();
                    xmlWriter.Close();
                }
            }
        }
    }
}

当然,现在我还有另一个问题要发布……那就是反序列化文件!

【讨论】:

  • 你也应该处理xmlWriter
  • XmlWriter 不是 IDisposable 对象。
  • 1, 2.
  • 很奇怪。我正在使用 .Net 4.5 和 Visual Studio。如果我输入 xmlWriter.Dispose() 我找不到方法。另外,如果我将 xmlWriter 放入 using 块中-它会在那时崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-06
  • 2023-04-01
相关资源
最近更新 更多