gpt4 book ai didi

.net - 在.NET中序列化许多对象时出现SerializationException

转载 作者:行者123 更新时间:2023-12-03 11:58:42 24 4
gpt4 key购买 nike

我遇到了在.NET中序列化许多对象的问题。对象图很大,正在使用一些新数据集,所以我得到:

System.Runtime.Serialization.SerializationException
"The internal array cannot expand to greater than Int32.MaxValue elements."

还有其他人达到这个极限吗?您如何解决的?

如果可能的话,我仍然可以使用内置的序列化机制,那将是很好的选择,但是似乎只需要自己滚动即可(并保持与现有数据文件的向后兼容性)

这些对象都是 POCO,并且正在使用 BinaryFormatter进行序列化。每个要序列化的对象都实现了 ISerializable来选择性地序列化其成员(其中一些在加载过程中会重新计算)。

看来这是MS( details here)的未解决问题,但已解决为Wont Fix。详细信息是(来自链接):

Binary serialization fails for object graphs with more than ~13.2 million objects. The attempt to do so causes an exception in ObjectIDGenerator.Rehash with a misleading error message referencing Int32.MaxValue.

Upon examination of ObjectIDGenerator.cs in the SSCLI source code, it appears that larger object graphs could be handled by adding additional entries into the sizes array. See the following lines:

// Table of prime numbers to use as hash table sizes. Each entry is the
// smallest prime number larger than twice the previous entry.
private static readonly int[] sizes = {5, 11, 29, 47, 97, 197, 397,
797, 1597, 3203, 6421, 12853, 25717, 51437, 102877, 205759,
411527, 823117, 1646237, 3292489, 6584983};

However, it would be nice if serialization worked for any reasonable size of the object graph.

最佳答案

我尝试重现该问题,但是即使13+百万个对象中的每个对象只有2个字节,代码也永远需要花很长时间才能运行。因此,我怀疑如果将数据更好地打包到自定义ISerialize实现中,您不仅可以解决问题,而且可以显着提高性能。不要让序列化器深入到您的结构中,而要在对象图炸裂成数十万个数组元素或更多的点时将其切断(因为如果您有很多对象,它们可能很小)否则您将无法将其保存在内存中)。以以下示例为例,该示例允许序列化程序查看类B和C,但是手动管理类A的集合:

class Program
{
static void Main(string[] args)
{
C c = new C(8, 2000000);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
bf.Serialize(ms, c);
ms.Seek(0, System.IO.SeekOrigin.Begin);
for (int i = 0; i < 3; i++)
for (int j = i; j < i + 3; j++)
Console.WriteLine("{0}, {1}", c.all[i][j].b1, c.all[i][j].b2);
Console.WriteLine("=====");
c = null;
c = (C)(bf.Deserialize(ms));
for (int i = 0; i < 3; i++)
for (int j = i; j < i + 3; j++)
Console.WriteLine("{0}, {1}", c.all[i][j].b1, c.all[i][j].b2);
Console.WriteLine("=====");
}
}

class A
{
byte dataByte1;
byte dataByte2;
public A(byte b1, byte b2)
{
dataByte1 = b1;
dataByte2 = b2;
}

public UInt16 GetAllData()
{
return (UInt16)((dataByte1 << 8) | dataByte2);
}

public A(UInt16 allData)
{
dataByte1 = (byte)(allData >> 8);
dataByte2 = (byte)(allData & 0xff);
}

public byte b1
{
get
{
return dataByte1;
}
}

public byte b2
{
get
{
return dataByte2;
}
}
}

[Serializable()]
class B : System.Runtime.Serialization.ISerializable
{
string name;
List<A> myList;

public B(int size)
{
myList = new List<A>(size);

for (int i = 0; i < size; i++)
{
myList.Add(new A((byte)(i % 255), (byte)((i + 1) % 255)));
}
name = "List of " + size.ToString();
}

public A this[int index]
{
get
{
return myList[index];
}
}

#region ISerializable Members

public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
UInt16[] packed = new UInt16[myList.Count];
info.AddValue("name", name);
for (int i = 0; i < myList.Count; i++)
{
packed[i] = myList[i].GetAllData();
}
info.AddValue("packedData", packed);
}

protected B(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
name = info.GetString("name");
UInt16[] packed = (UInt16[])(info.GetValue("packedData", typeof(UInt16[])));
myList = new List<A>(packed.Length);
for (int i = 0; i < packed.Length; i++)
myList.Add(new A(packed[i]));
}

#endregion
}

[Serializable()]
class C
{
public List<B> all;
public C(int count, int size)
{
all = new List<B>(count);
for (int i = 0; i < count; i++)
{
all.Add(new B(size));
}
}
}

关于.net - 在.NET中序列化许多对象时出现SerializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/569127/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com