2

コレクション内のオブジェクト (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;

これを行うためのより良い方法はありますか、それとも私は明らかに間違ったことをしていますか?

4

3 に答える 3

4

うまくいくように見えます、CF には予測できない制限があります。

xml は必須ですか? 20k レコードで試した覚えはありませんが、別のシリアライザーを使用することもできます。たとえば、protobuf-netは CF2 で動作します。うまくいくかは保証できませんが、試してみる価値はあります。

(特に、私は現在、コードをリファクタリングして、CF 内のいくつかの追加の「ジェネリック」制限を回避しようとしていますが、非常に複雑なオブジェクト モデルがない限り、これは影響しません)。


使用例を示します。この例も で問題なく動作しXmlSerializerますが、protobuf-net はスペースの 20% (または、文字がメモリ内でそれぞれ 2 バイトであると考える場合はスペースの 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<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
    }
}

さらに助けが必要な場合はお知らせください-この件については一日中話すことができます;-p標準のxml属性([XmlElement(Order=1)])からだけで機能することに注意してください-明確にするために、より具体的な属性[ProtoMember(1)]などを使用しました。これにより、シリアライゼーションをきめ細かく制御することもできます (ジグザグ vs ツースコンプリメント、グループ化 vs 長さプレフィックスなど)。

于 2009-04-28T08:01:06.330 に答える
0

おそらく、(コレクションを 1 つの大きなブロックとして永続化するのではなく) 個々のオブジェクトを永続化することを検討できます。その場合は、codeplex で作成した NFileStorage プロジェクトを使用することをお勧めします。nfilestorage.codeplex.com (これは CF 用に特別に作成されたものではないため、それと互換性があるかどうかはわかりません)...

がんばれ、ゲルト・ヤン

于 2009-05-26T07:07:40.423 に答える
0

アプリケーションのメモリ消費に関する指標はありますか? WM で実行していると仮定しています。つまり、各プロセスのアドレス空間は 32MB に制限されています。大きな XML では、実際にメモリ不足になる可能性があります。

于 2009-04-28T09:11:27.597 に答える