C#Compact Framework – 使用XmlSerializer.Serialize的OutOfMemoryException

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

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记录,但另一种选择可能是尝试使用不同的序列化程序 – 例如, protobuf-net适用于CF2。 我不能保证它会起作用,但它可能值得一试。

(特别是,我正在重构代码以尝试解决CF中的一些额外的“generics”限制 – 但除非你有一个非常复杂的对象模型,否则这不会影响你)。


显示用法的示例; 请注意,此示例对XmlSerializer也可以正常工作,但protobuf-net仅使用20%的空间(如果您认为内存中的每个字符为两个字节,则占用空间的10%):

 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 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(); 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 } } 

如果您需要更多帮助,请告诉我 - 我可以整天谈论这个主题;-p请注意,它可以仅使用标准的xml属性( [XmlElement(Order=1)] ) - 我使用了更具体的[ProtoMember(1)]等清晰度。 这也允许对序列化进行细粒度控制(Z字形与两个补码,分组与长度前缀等)。

您对应用程序的内存消耗有任何指标吗? 我假设您正在运行WM,这意味着每个进程的地址空间限制为32MB。 使用大型XML,您实际上可能会耗尽内存。

也许你可以考虑坚持单个对象(而不是将集合持久化为一个大块)。 如果是这样,您可能想要使用我在codeplex上创建的NFileStorage项目; nfilestorage.codeplex.com(这个不是专门为CF做的,所以无法分辨它是否与那个兼容)…

祝你好运,Gert-Jan