SerializationException when serializing lots of objects in .NET

后端 未结 9 806
深忆病人
深忆病人 2020-12-10 01:41

I\'m running into problems serializing lots of objects in .NET. The object graph is pretty big with some of the new data sets being used, so I\'m getting:

Sy         


        
相关标签:
9条回答
  • 2020-12-10 02:38

    Do you need to fetch all the data at the same time? Thirteen million objects is a lot of information to handle at once.

    You could implement a paging mechanism and fetch the data in smaller chunks. And it might increase the responsiveness of the application, since you wouldn't have to wait for all those objects to finish serializing.

    0 讨论(0)
  • 2020-12-10 02:41

    I tried reproducing the problem, but the code just takes forever to run even when each of the 13+ million objects is only 2 bytes. So I suspect you could not only fix the problem, but also significantly improve performance if you pack your data a little better in your custom ISerialize implementations. Don't let the serializer see so deep into your structure, but cut it off at the point where your object graph blows up into hundreds of thousands of array elements or more (because presumably if you have that many objects, they're pretty small or you wouldn't be able to hold them in memory anyway). Take this example, which allows the serializer to see classes B and C, but manually manages the collection of class 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));
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 02:43

    Sounds like you ran up against an internal limitation in the framework. You could write your own serialization using BinaryReader/Writer or DataContractSerializer or whatever, but it's not ideal I know.

    0 讨论(0)
提交回复
热议问题