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