c# - "Exception of type ' System.OutOfMemoryException ' was thrown"同时使用 xmlserializer

标签 c# .net

我正在使用以下代码获取 xml 字符串。

public static string ToXMLString(object obj, string nodeName)
{
    XmlSerializer xmlSerializer = default(XmlSerializer);
    string xml = string.Empty;
    StreamReader r = default(StreamReader);
    try
    {
        if (obj != null)
        {
            using (MemoryStream m = new MemoryStream())
            {
                using (XmlWriter writer = XmlWriter.Create(m, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true }))
                {
                    // Don't include XML namespace
                    XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
                    xmlnsEmpty.Add("", "");
                    if (xmlSerializer == null)
                        xmlSerializer = new XmlSerializer(obj.GetType(), new XmlRootAttribute(nodeName));
                    xmlSerializer.Serialize(writer, obj, xmlnsEmpty);

                    m.Flush();
                    m.Position = 0;

                    r = new StreamReader(m);
                    xml = r.ReadToEnd();
                    xmlSerializer = null;
                }
            }
        }

        return xml;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        throw;
    }
    finally
    {
        r.Close();
        r.Dispose();
    }
    //XmlSerializer xmlSerializer;

}

我有一个使用该方法运行的循环,一段时间后我得到如下内存不足异常:

异常的原因可能是什么? using 语句真的在处理流吗?或者我可以使用其他什么替代方法?

最佳答案

我认为这里的问题是程序集饱和。 XmlSerializer 通过动态生成程序集来工作;如果您使用 XmlSerializer(Type) 构造函数,它会缓存它并查找它;但对于任何其他构造函数,它不会。并且程序集不能(通常)被卸载。所以你只会得到越来越多的程序集来吞噬你的内存。如果您在循环中运行它,则需要缓存序列化程序:

using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;


public static class Program
{
    static void Main()
    {
        // the loop here is from your comment
        for (int i = 0; i < 10000000; i++) { ToXMLString("test", string.Format("test")); Console.WriteLine(i); }
    }

    // why is this Hashtable? due to the threading semantics!
    private static readonly Hashtable serializerCache = new Hashtable();

    public static string ToXMLString(object obj, string nodeName)
    {
        if (obj == null) throw new ArgumentNullException("obj");
        Type type = obj.GetType();
        var cacheKey = new { Type = type, Name = nodeName };
        XmlSerializer xmlSerializer = (XmlSerializer)serializerCache[cacheKey];
        if (xmlSerializer == null)
        {
            lock (serializerCache)
            { // double-checked
                xmlSerializer = (XmlSerializer)serializerCache[cacheKey];
                if (xmlSerializer == null)
                {
                    xmlSerializer = new XmlSerializer(type, new XmlRootAttribute(nodeName));
                    serializerCache.Add(cacheKey, xmlSerializer);
                }
            }
        }
        try
        {

            StringWriter sw = new StringWriter();
            using (XmlWriter writer = XmlWriter.Create(sw,
                new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true }))
            {
                // Don't include XML namespace
                XmlSerializerNamespaces xmlnsEmpty = new XmlSerializerNamespaces();
                xmlnsEmpty.Add("", "");
                xmlSerializer.Serialize(writer, obj, xmlnsEmpty);
            }
            return sw.ToString();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);
            throw;
        }
    }
}

关于c# - "Exception of type ' System.OutOfMemoryException ' was thrown"同时使用 xmlserializer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8999159/

相关文章:

c# - 我想从 Windows MDI 子窗体中删除图标

c# - 检测 Windows 服务中注销的用户

c# - 将 PropertyInfo.PropertyType 转换为枚举

c# - 在 c# 和 c dll 之间使用通用颜色值

c# - 在 C# 中调用多个 "SQL DataReader"的正确方法是什么?

c# - 在 Windows 窗体中在鼠标悬停时显示图像?

c# - 挪威 CultureInfo 的问题

c# - WrapPanel 不在 WPF ListView 中换行

C# 连接到端口 990 时 FTPS 卡住/超时

.Net Control.Tag - 常见和不寻常的用途