我有一个使用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,因此必须发生其他事情。
有什么想法吗?
答案 0 :(得分:1)
有几件事导致这种行为:
32位进程只能处理2GB(有时是3GB)的虚拟地址空间(1-2GB是保留的,32位指针只能处理4GB)。
.NET在特殊的大对象堆上存储大对象(大于85000字节)。默认情况下,此堆不是压缩(在4.5.1之前的.NET版本中 - 从未压缩过)。假设您分配了40MB,然后是10MB,然后是70MB内存。过了一会儿,40MB和70MB被垃圾收集了。现在你要分配100MB的块。如果压缩大对象堆 - 您可以拥有至少110MB的连续空闲地址空间。但事实并非如此,因此你有两个40MB和70MB的差距,因此无法分配你的100MB大块。
因此,即使该机器上有足够的可用物理RAM(即使没有 - 总是交换),您也可能无法获得指向连续大块地址空间的指针。在这种情况下,OutOfMemoryException
将被抛出。
解决这个问题的几种方法:
.NET 4.5.1提供了一种压缩大对象堆的方法,但它并没有真正解决你的问题,我想,只是有点延迟它。您可以通过执行以下操作来压缩LOH一次(您不能强制它在每个集合上压缩):
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
答案 1 :(得分:0)
尝试使用WCF WebServiceHost并将配置设置为不限制缓冲区或消息大小:
user_wrdp12