C# 当我试图从web服务读取结果时,如何删除OutOfMemoryException?

C# 当我试图从web服务读取结果时,如何删除OutOfMemoryException?,c#,C#,我正在使用一个web服务,web服务返回大约10万条记录,但是当我尝试用下面的代码读取它时,它会读取一次,但在接下来的时间OutOfMemoryException错误出现,有人知道我是否读取了错误的信息,或者我如何删除异常 WebResponse response2 = request2.GetResponse(); string Status2 = ((HttpWebResponse)response2).StatusDescription;

我正在使用一个web服务,web服务返回大约10万条记录,但是当我尝试用下面的代码读取它时,它会读取一次,但在接下来的时间OutOfMemoryException错误出现,有人知道我是否读取了错误的信息,或者我如何删除异常

        WebResponse response2 = request2.GetResponse();

        string Status2 = 
        ((HttpWebResponse)response2).StatusDescription;


        StringBuilder datos = new StringBuilder();


        StringBuilder _stringBuilder = new StringBuilder();
        try
        {

            using ( dataStream2 = response2.GetResponseStream())
            {
                using (StreamReader reader2 = new 
                StreamReader(dataStream2))
                {
                    while (!reader2.EndOfStream)
                    {
                        char[] _buffer = new char[4096];
                        reader2.ReadBlock(_buffer, 0, _buffer.Length);
                        var _bufferString = new String(_buffer);
                        _stringBuilder.Append(_bufferString);
                    }
                }
            }
        }
        catch (Exception e)
        {
        }

    var result2 = JsonConvert.DeserializeObject<RootObject> 
      (_stringBuilder.ToString());

       dataStream2.Close();
        response2.Close();
但是错误会自动重复

理论上,4K块之间会重复使用_buffer对象,但可能会发生新的分配。此外,您正在读取字节,然后创建UTF-16字符串,与通常作为UTF-8发送的数据(如果是web服务)相比,该字符串的内存量增加了一倍。最后,您将字符串附加到StringBuilder,它在需要扩展缓冲区时从其缓冲区堆内存进行复制,然后丢弃其缓冲区堆内存。垃圾收集器将很难跟上字符串和StringBuilder分配,因为它们都在分割堆

如果web服务发送回的数据量占可用堆内存的很大一部分,那么由于字符编码和多次分配的倍增效应,这很容易导致OOM错误


通过使用StringReader一次读取一行来修复此问题,如果您知道响应的大小(以字节为单位)(从HTTP头),请将其作为参数提供给StringBuilder构造函数;它将从最初分配给该大小的缓冲区开始,以便只分配一次。还考虑将行缓存到磁盘而不是String Bu建器。

这是一种非常可疑的读取字符串响应的方法。您可能需要添加更多的代码。如何处理生成的
\u stringBuilder
对象?如果您在代码中保留了大量这些内容,那么在某个时候,应用程序将耗尽可用的内存。但是,如果在读取下一个对象之前丢弃了大型对象,那么内存将在下一次运行块时可用(通过垃圾收集)。如果它使用UTF编码,则可能会将字符拆分为单独的块,因此无法正常工作。我会使用StringReader类
100000条记录,
有多少字节?
已经发送了内存异常
OK,所以OOM在服务器上,而不是客户端上?如果是这样,请在你的问题中说得更清楚。将代码更改为我理解的代码,但它会不断重复错误,第一次读得很好,但如果我再次这样做,则会出现相同的错误。我回答问题时假设错误发生在客户端上,但是现在还不清楚您是否看到从服务器返回的OOM消息。@AlexZ您可以直接使用JsonConvert流API吗?看见
   using ( dataStream2 = response2.GetResponseStream())
            {
                using (StreamReader reader2 = new 
   StreamReader(dataStream2))
                {
                    while (!reader2.EndOfStream)
                    {
                        char[] _buffer = new char[30720];
                        reader2.ReadBlock(_buffer, 0, _buffer.Length);
                        var _bufferString = new String(_buffer);
                        _stringBuilder.Append(_bufferString);
                    }
                    reader2.Close();
                }

            }