C#Compact Framework-带有XmlSerializer.Serialize的OutOfMemoryException

C#Compact Framework-带有XmlSerializer.Serialize的OutOfMemoryException,c#,serialization,compact-framework,stringwriter,C#,Serialization,Compact Framework,Stringwriter,我正在尝试序列化集合中的大量对象集合(20000个)。我使用以下代码执行此操作: XmlSerializer xs = new XmlSerializer(deserialized.GetType()); StringWriter sw; using (sw = new StringWriter()) { xs.Serialize(sw, deserialized); // OutOfMemoryException here } string packet = sw.ToString

我正在尝试序列化集合中的大量对象集合(20000个)。我使用以下代码执行此操作:

XmlSerializer xs = new XmlSerializer(deserialized.GetType());
StringWriter sw;
using (sw = new StringWriter())
{
   xs.Serialize(sw, deserialized);   // OutOfMemoryException here
}

string packet = sw.ToString();
return packet;
有没有更好的方法来实现这一点,或者我是在做一些明显错误的事情?

看起来它应该可以工作,但CF确实有不可预测的局限性

xml是一种需求吗?我不记得用20k记录尝试过,但另一个选择可能是尝试使用不同的序列化程序-例如,在CF2上工作。我不能保证它会起作用,但也许值得一试

(特别是,我目前正在重构代码,试图在CF中解决一些额外的问题——但除非您有一个非常复杂的对象模型,否则这不会影响您)


显示用法的示例;注意,这个例子也适用于<代码> XMLSerialSuth,但是OrthBuffnet只使用20%的空间(或者如果您认为每个字符在内存中都是两个字节),则占用空间的10%:

使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Xml.Serialization;
使用ProtoBuf;
[可序列化,协议]
公共课系
{
[原成员(1)]
公共字符串名称{get;set;}
[原成员(2)]
公共列表人员{get;set;}
}
[可序列化,协议]
公共阶层人士
{
[原成员(1)]
公共int Id{get;set;}
[原成员(2)]
公共字符串名称{get;set;}
[原成员(3)]
公共日期时间出生日期{get;set;}
}
静态类程序
{
[MTA线程]
静态void Main()
{
Department dept=新部门{Name=“foo”};
部门人员=新列表();
随机兰德=新随机(123456);
对于(int i=0;i<20000;i++)
{
Person=新人();
person.Id=rand.Next(50000);
person.DateOfBirth=DateTime.Today.AddDays(-rand.Next(2000));
person.Name=“固定姓名”;
部门人员增加(人);
}
字节[]原始;
使用(MemoryStream ms=new MemoryStream())
{
序列化程序。序列化(ms,部门);
raw=ms.ToArray();//473399字节
}
XmlSerializer ser=新的XmlSerializer(typeof(Department));
StringWriter sw=新的StringWriter();
序列号(软件、部门);
字符串s=sw.ToString();//2115693个字符
}
}
如果你需要更多的帮助,请告诉我——我可以整天谈论这个话题-P
请注意,它可以仅从标准xml属性(
[xmlement(Order=1)]
)工作-为了清晰起见,我使用了更具体的
[ProtoMember(1)]
等。这还允许对序列化进行细粒度的控制(Z字形与TwosComplient、分组与长度前缀等)。

您对应用程序的内存消耗有什么衡量标准吗?我假设您在WM上运行,这意味着每个进程的地址空间限制为32MB。使用一个大的XML,你可能已经耗尽了内存。

也许你可以考虑坚持单个对象(而不是将集合保持为一个大的块)。如果是这样,您可能希望使用我在codeplex上创建的NFileStorage项目;nfilestorage.codeplex.com(这一款不是专门为CF设计的,因此无法判断它是否与那一款兼容)

祝你好运,
Gert Jan

要补充的是,多亏了Protobuf.Net,我现在正在序列化20000条记录,然后在29秒内将其保存到一个文件中(在我最大的表结构中)。然后我可以使用反序列化器在28秒内加载该文件)。感谢度量更新-感谢。这些时间安排令人满意吗?信息方面,在CF 3.5上,它的速度更快,因为它可以使用Delegate.CreateDelegate优化属性访问。不,谢谢,速度更快。使用XmlSerializer,20000条记录需要3分钟50秒。如果您知道您的项目与CF一起工作,那么我对您提供它作为解决方案没有问题,但如果您不知道,请不要发布它,希望只是为了提高曝光率。自己测试场景,如果它有效,请让我们知道。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using ProtoBuf;

[Serializable, ProtoContract]
public class Department
{
    [ProtoMember(1)]
    public string Name { get; set; }
    [ProtoMember(2)]
    public List<Person> People { get; set; }
}

[Serializable, ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public string Name { get; set; }
    [ProtoMember(3)]
    public DateTime DateOfBirth { get; set; }
}


static class Program
{
    [MTAThread]
    static void Main()
    {
        Department dept = new Department { Name = "foo"};
        dept.People = new List<Person>();
        Random rand = new Random(123456);
        for (int i = 0; i < 20000; i++)
        {
            Person person = new Person();
            person.Id = rand.Next(50000);
            person.DateOfBirth = DateTime.Today.AddDays(-rand.Next(2000));
            person.Name = "fixed name";
            dept.People.Add(person);
        }

        byte[] raw;
        using (MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize(ms, dept);
            raw = ms.ToArray(); // 473,399 bytes
        }

        XmlSerializer ser = new XmlSerializer(typeof(Department));
        StringWriter sw = new StringWriter();
        ser.Serialize(sw, dept);
        string s = sw.ToString(); // 2,115,693 characters
    }
}