我在这句话中得到了间歇性的“内存不足”异常:
return ms.ToArray();
在这种方法中:
public static byte[] Serialize(Object inst)
{
Type t = inst.GetType();
DataContractSerializer dcs = new DataContractSerializer(t);
MemoryStream ms = new MemoryStream();
dcs.WriteObject(ms, inst);
return ms.ToArray();
}
我该如何预防呢?有更好的方法吗?
ms的长度是182,870,206字节(174.4 MB)
我将它放入一个字节数组,以便我可以通过压缩运行它并将其存储到磁盘。数据(显然)是我在Silverlight应用程序启动时从WCF服务器下载的自定义类的大型列表。我正在对它进行序列化并对其进行压缩,因此它在隔离存储中仅使用大约6MB。下次用户从Web访问并运行silverlight应用程序时,我会检查时间戳,如果好,我只是从隔离打开文件,解压缩,反序列化并加载我的结构。我将整个结构保留在内存中,因为应用程序主要是围绕操作此结构的内容。
@configurator是正确的。阵列的大小太大了。我通过自己的序列化程序,通过声明[list record count *每个记录的字节数]的字节数组,然后使用这样的语句直接填充它来填充它:
Buffer.BlockCopy(
BitConverter.GetBytes(node.myInt),0,destinationArray,offset,sizeof(int));
offset += sizeof(int);
这是为了取回它:
newNode.myInt= BitConverter.ToInt32(sourceByteArray,offset);
offset += sizeof(int);
然后我将其压缩并存储到隔离存储中。
我的尺寸从DataBontractSerializer的174MB变为我的14MB。 压缩后,它在隔离存储中从6MB传输到1MB文件。
感谢Configurator和Filip的帮助。
答案 0 :(得分:3)
问题似乎是你期望返回180MB字节数组。这意味着框架需要找到并分配一个连续的180MB可用内存来复制流数据,这通常很难 - 因此OutOfMemoryException。如果需要继续处理这么大的内存,请使用内存流本身(根据需要读取和写入)来保存缓冲区;否则,将其保存到文件(或者您需要的其他任何地方,例如通过网络提供),而不是使用内存流。
我应该提一下,内存流也有自己的180MB阵列,所以也有点麻烦,并且在序列化过程中可能会导致OutOfMemory - 它可能会更好(如更强大)您可以将其序列化为temporary file。您可能还需要考虑更紧凑但可能更不易读的序列化格式,如json,二进制序列化或协议缓冲区。
在回复评论时:要直接序列化到磁盘,请使用FileStream
代替MemoryStream
:
public static void Serialize(Object inst, string filename)
{
Type t = inst.GetType();
DataContractSerializer dcs = new DataContractSerializer(t);
using (FileStream stream = File.OpenWrite(filename)) {
dcs.WriteObject(ms, inst);
}
}
答案 1 :(得分:0)
我不知道你是如何使用该代码的,但有一点让我感到震惊的是你没有释放你的资源。例如,如果您使用大量大型对象多次调用Serialize(obj)
,则最终会使用大量未直接释放的内存,但GC
应正确处理,但你应该总是释放你的资源。
我尝试过这段代码:
public static byte[] Serialize(object obj)
{
Type type = obj.GetType();
DataContractSerializer dcs = new DataContractSerializer(type);
using (var stream = new MemoryStream())
{
dcs.WriteObject(stream, obj);
return stream.ToArray();
}
}
在控制台应用程序中使用以下Main
- 方法
static void Main(string[] args)
{
var filipEkberg = new Person {Age = 24, Name = @"Filip Ekberg"};
var obj = Serialize(filipEkberg);
}
然而,我的byte
阵列并不像你的那么大。 Having a look at this similar issue,您可能需要考虑查看protobuf-net。
了解您打算如何处理序列化数据可能也很有趣,您是否需要将其作为byte
- 数组或者是否也可以将XML写入文本文件?< / p>
答案 2 :(得分:-1)
尝试序列化为流(即FileStream)而不是字节数组。这样,您可以在没有OutOfMemory异常的情况下序列化数十亿字节的数据。
public static void Serialize<T>(T obj, string path)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
Stream stream = File.OpenWrite(path);
serializer.WriteObject(stream, obj);
}
public static T Deserialize<T>(string path)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
Stream stream = File.OpenRead(path);
return (T)serializer.ReadObject(stream);
}
答案 3 :(得分:-4)
尝试将内存流位置设置为0,然后仅调用ToArray()。
问候。