我在线程上使用下面的代码(在ui中显示进度对话框)从ASP.Net MVC Web服务中读取json字符串。数据可以介于1 mb和4 mb之间。
public static class WebRequestEx
{
public static string ExecuteRequestReadToEnd(this WebRequest req)
{
var resp = req.GetResponse();
using (var resps = resp.GetResponseStream())
{
StringBuilder sb = new StringBuilder();
// read through the stream loading up the string builder
using (var respRdr = new StreamReader(resps))
{
//return respRdr.ReadToEnd();
while (!respRdr.EndOfStream)
{
sb.Append(respRdr.ReadLine());
}
return sb.ToString();
}
}
}
}
堆栈跟踪如下。
I/mono (15666): Stacktrace:
I/mono (15666):
I/mono (15666): at System.Threading.WaitHandle.set_Handle (intptr) <0x0008b>
I/mono (15666): at System.Threading.EventWaitHandle..ctor (bool,System.Threading.EventResetMode) <0x00053>
I/mono (15666): at System.Threading.ManualResetEvent..ctor (bool) <0x0001f>
I/mono (15666): at (wrapper remoting-invoke-with-check) System.Threading.ManualResetEvent..ctor (bool) <0xffffffff>
I/mono (15666): at System.Net.WebAsyncResult.get_AsyncWaitHandle () <0x00073>
I/mono (15666): at System.Net.WebAsyncResult.WaitUntilComplete (int,bool) <0x00033>
I/mono (15666): at System.Net.WebConnectionStream.Read (byte[],int,int) <0x000b3>
I/mono (15666): at System.IO.StreamReader.ReadBuffer () <0x00047>
I/mono (15666): at System.IO.StreamReader.ReadLine () <0x0014b>
I/mono (15666): at System.WebRequestEx.ExecuteRequestReadToEnd (System.Net.WebRequest) <0x000ab>
问题是每次都不会发生这种情况并且是间歇性的。这很糟糕,因为它导致整个应用程序冻结,进度对话框因用户无法对应用程序执行任何操作而停滞不前。我在调用代码中有一个try / catch块,但是这个异常似乎绕过它。
我之前使用的是ReadToEnd,并且间歇性地爆发了,所以我逐渐切换到了阅读。
堆栈跟踪不是特别有用,因为在Readline()中似乎正在进行某些操作。
思想/忠告/替代?
答案 0 :(得分:0)
尝试使用这个:
public static string ExecuteRequestReadToEnd(this WebRequest req)
{
var resp = req.GetResponse();
using (var resps = resp.GetResponseStream())
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = resps.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
var content = ms.ToArray();
return Encoding.UTF8.GetString(content, 0, content.Length);
}
}
}
答案 1 :(得分:0)
您需要增加maxArrayLength值,因为返回的byte []数组超过了16348的大小。您可以为maxArrayLength设置的最大值也是最大Int32数,它等于2147483647.修改此设置,您的Web服务将能够在您的Web服务和客户端应用程序之间传输大数据。
在 Web.config 中,生成客户端的Web服务引用绑定。
“已超出传入邮件的最大邮件大小限额(65536)。要增加配额,请在相应的绑定元素上使用MaxReceivedMessageSize属性。”
将其设置为最大的32 ^ 31 - 1或2147483647最大32位数。
注意transferMode,默认情况下是缓冲。
transferMode的其他枚举:
对于那些不知道的人,Buffered意味着传输将整个消息保存在内存缓冲区中,直到传输完成。流式传输意味着只缓冲邮件头,而邮件正文将作为流公开。
将maxReceivedMessageSize从65536更改为2147483647 - 如果您保留transferMode =“Buffered”,我们可能会收到另一个错误:
对于TransferMode.Buffered,MaxReceivedMessageSize和MaxBufferSize必须是相同的值。参数名称:bindingElement
如果整个消息被缓冲,则两个属性都需要相同的值,MaxReceivedMessageSize大于MaxBufferSize。
您有两种选择: a)将MaxBufferSize更改为2147483647的大小 b)将transferMode设置为:Streamed,StreamedRequest或StreamedResponse。
“使用缓冲或流式传输的决定是端点对HTTP传输的本地决定。对于HTTP传输,传输模式不会通过连接传播,也不传播到代理服务器或其他中介。设置传输模式在服务合同的描述中没有反映出来。在为服务生成代理之后,您可以(允许但不要求)编辑配置文件,以获取要与流传输一起使用的服务以设置传输模式。和命名管道传输,传输模式作为策略断言传播。“ http://msdn.microsoft.com/en-us/library/system.servicemodel.transfermode.aspx
答案 2 :(得分:0)
除非您对WebRequest
有特殊要求,否则应使用WebClient
。
像DownloadString
和(甚至更好)DownloadStringAsync
这样的方法可以防止您处理响应位,因为它很容易分配给大量内存和临时字符串,这会影响您的应用程序性能