OutOfMemoryException从WebServices接收数据

时间:2016-05-26 07:39:47

标签: c# .net web-services wcf out-of-memory

我有一个使用WCF客户端与Java webservices通信的应用程序。其中一个服务返回一个中等大的结果(大约100 Mb),有时我们得到一个OutOfMemoryException:

  

System.IO.MemoryStream.set_Capacity(Int32)已
  System.IO.MemoryStream.EnsureCapacity(Int32)已
  System.IO.MemoryStream.Write(Byte [],Int32,Int32)
  System.Xml.XmlMtomReader + MimePart.GetBuffer(Int32,Int32 ByRef)
  System.Xml.XmlMtomReader.Initialize(System.IO.Stream,System.String,   System.Xml.XmlDictionaryReaderQuotas,Int32)
  System.Xml.XmlMtomReader.SetInput(System.IO.Stream,   System.Text.Encoding [],System.String,   System.Xml.XmlDictionaryReaderQuotas,Int32,   System.Xml.OnXmlDictionaryReaderClose)
  System.ServiceModel.Channels.MtomMessageEncoder.TakeStreamedReader(System.IO.Stream,   System.String)
  System.ServiceModel.Channels.MtomMessageEncoder.ReadMessage(System.IO.Stream,   Int32,System.String)
  System.ServiceModel.Channels.HttpInput.ReadStreamedMessage(System.IO.Stream)   System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(System.Exception的   为ByRef)
  System.ServiceModel.Channels.HttpChannelFactory + HttpRequestChannel + HttpChannelRequest.WaitForReply(System.TimeSpan)   System.ServiceModel.Channels.RequestChannel.Request(System.ServiceModel.Channels.Message,   System.TimeSpan)
  System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message,   System.TimeSpan)
  System.ServiceModel.Channels.ServiceChannel.Call(System.String,   Boolean,System.ServiceModel.Dispatcher.ProxyOperationRuntime,   System.Object [],System.Object [],System.TimeSpan)
  System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage,   System.ServiceModel.Dispatcher.ProxyOperationRuntime)
  System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData   ByRef,Int32)

我们的WCF客户端....

数据量不足以创建真正的OutOfMemoryException,因为应用程序是32位应用程序,消耗大约400 - 600 MB,响应速度为100Mb,因此必须发生其他事情。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

有几件事导致这种行为:

  1. 32位进程只能处理2GB(有时是3GB)的虚拟地址空间(1-2GB是保留的,32位指针只能处理4GB)。

  2. .NET在特殊的大对象堆上存储大对象(大于85000字节)。默认情况下,此堆不是压缩(在4.5.1之前的.NET版本中 - 从未压缩过)。假设您分配了40MB,然后是10MB,然后是70MB内存。过了一会儿,40MB和70MB被垃圾收集了。现在你要分配100MB的块。如果压缩大对象堆 - 您可以拥有至少110MB的连续空闲地址空间。但事实并非如此,因此你有两个40MB和70MB的差距,因此无法分配你的100MB大块。

  3. 因此,即使该机器上有足够的可用物理RAM(即使没有 - 总是交换),您也可能无法获得指向连续大块地址空间的指针。在这种情况下,OutOfMemoryException将被抛出。

    解决这个问题的几种方法:

    1. 使用64位进程。
    2. 通过重用字节数组来重用(池)内存块。例如,WCF提供(并使用)此类BufferManager
    3. .NET 4.5.1提供了一种压缩大对象堆的方法,但它并没有真正解决你的问题,我想,只是有点延迟它。您可以通过执行以下操作来压缩LOH一次(您不能强制它在每个集合上压缩):

      GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
      GC.Collect();      
      

答案 1 :(得分:0)

尝试使用WCF WebServiceHost并将配置设置为不限制缓冲区或消息大小:

user_wrdp12