无法分配268435456字节的托管内存缓冲区。可用内存量可能很低

时间:2016-08-04 11:58:12

标签: c# .net wcf

我试图通过WCF服务调用将一些大数据保存到数据库。我无法调用该服务。它抛出一个错误:

无法分配268435456字节的托管内存缓冲区。可用内存量可能很低

public async Task<int> UploadExportPackage(DTO.Upload.UploadPackage package)
{
    int result = await serviceProxy.UploadResultsAsync(package);
    return result;
}

服务器端配置:

      

    <!-- 
      Place limits on the amount of data that can be received in one go.
      This helps to protect the server from attack and abuse.
    -->
    <binding name="primaryBinding"
             maxReceivedMessageSize="6000000"
             maxBufferSize="6000000"
             maxBufferPoolSize="12000000">

      <readerQuotas maxArrayLength="6000000"
                    maxStringContentLength="6000000" />

      <!--
          Set the security mode. Apply at:
            - Transport layer
            - Message layer
      -->
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="UserName" />
      </security>
    </binding>
  </basicHttpsBinding>
</bindings>

堆栈追踪:

Exception no: 0 

下一个例外: 消息:

无法分配268435456字节的托管内存缓冲区。可用内存量可能很低。

堆栈跟踪: 服务器堆栈跟踪:    在System.Runtime.Fx.AllocateByteArray(Int32大小)    在System.Runtime.InternalBufferManager.PooledBufferManager.TakeBuffer(Int32 bufferSize)    在System.ServiceModel.Channels.BufferManagerOutputStream.Init(Int32 initialSize,Int32 maxSizeQuota,Int32 effectiveMaxSize,BufferManager bufferManager)    在System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(消息消息,BufferManager bufferManager,Int32 initialOffset,Int32 maxSizeQuota)    at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(消息消息,Int32 maxMessageSize,BufferManager bufferManager,Int32 messageOffset)    在System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(消息消息,布尔值shouldRecycleBuffer)    在System.ServiceModel.Channels.HttpOutput.SendAsyncResult.SendWithoutChannelBindingToken()    在System.ServiceModel.Channels.HttpOutput.SendAsyncResult.Send()    在System.ServiceModel.Channels.HttpOutput.SendAsyncResult..ctor(HttpOutput httpOutput,HttpResponseMessage httpResponseMessage,Boolean suppressEntityBody,TimeSpan timeout,AsyncCallback callback,Object state)    在System.ServiceModel.Channels.HttpOutput.BeginSendCore(HttpResponseMessage httpResponseMessage,TimeSpan超时,AsyncCallback回调,对象状态)    在System.ServiceModel.Channels.HttpChannelFactory 1.HttpRequestChannel.HttpChannelAsyncRequest.SendWebRequest() at System.ServiceModel.Channels.HttpChannelFactory 1.HttpRequestChannel.HttpChannelAsyncRequest.BeginSendRequest(消息消息,TimeSpan超时)    在System.ServiceModel.Channels.RequestChannel.BeginRequest(消息消息,TimeSpan超时,AsyncCallback回调,对象状态)    在System.ServiceModel.Channels.SecurityChannelFactory 1.RequestChannelSendAsyncResult.BeginSendCore(IRequestChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, Object state) at System.ServiceModel.Security.ApplySecurityAndSendAsyncResult 1.OnSecureOutgoingMessageComplete(消息消息)    在System.ServiceModel.Security.ApplySecurityAndSendAsyncResult 1.Begin(Message message, SecurityProtocolCorrelationState correlationState) at System.ServiceModel.Channels.SecurityChannelFactory 1.SecurityRequestChannel.BeginRequest(消息消息,TimeSpan超时,AsyncCallback回调,对象状态)    在System.ServiceModel.Dispatcher.RequestChannelBinder.BeginRequest(消息消息,TimeSpan超时,AsyncCallback回调,对象状态)    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartSend(Boolean completedSynchronously)    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishEnsureOpen(IAsyncResult result,Boolean completedSynchronously)    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartEnsureOpen(Boolean completedSynchronously)    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishEnsureInteractiveInit(IAsyncResult result,Boolean completedSynchronously)    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartEnsureInteractiveInit()    在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.Begin()    at System.ServiceModel.Channels.ServiceChannel.BeginCall(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,TimeSpan timeout,AsyncCallback callback,Object asyncState)    在System.ServiceModel.Channels.ServiceChannel.BeginCall(ServiceChannel通道,ProxyOperationRuntime操作,Object [] ins,AsyncCallback回调,Object asyncState)    at System.Threading.Tasks.TaskFactory 1.FromAsyncImpl[TArg1,TArg2,TArg3](Func 6 beginMethod,Func 2 endFunction, Action 1 endAction,TArg1 arg1,TArg2 arg2,TArg3 arg3,Object state,TaskCreationOptions creationOptions)    在System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateGenericTask [T](ServiceChannel频道,ProxyOperationRuntime操作,Object [] inputParameters)    在System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateGenericTask(ServiceChannel频道,ProxyOperationRuntime操作,Object [] inputParameters)    在System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateTask(ServiceChannel频道,IMethodCallMessage methodCall,ProxyOperationRuntime操作)    在System.ServiceModel.Channels.ServiceChannelProxy.InvokeTaskService(IMethodCallMessage methodCall,ProxyOperationRuntime操作)    在System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

在[0]处重新抛出异常:    在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)    在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&amp; msgData,Int32 type)    在RossendaleClient8.DAL.RR.IRossendaleService.UploadResultsAsync(UploadPackage包)    在RossendaleClient8.DAL.RR.RossendaleServiceClient.UploadResultsAsync(UploadPackage包)    在RossendaleClient8.DAL.RossendaleServiceClient.d__13.MoveNext()

下一个例外: 消息:

类型的异常&#39; System.OutOfMemoryException&#39;被扔了。

堆栈跟踪:在System.Runtime.Fx.AllocateByteArray(Int32 size)

5 个答案:

答案 0 :(得分:6)

如果您的绑定允许,请尝试使用distros good。您还可以查看TransferMode.Streamed。 来自MSDN:

  
      
  • 缓冲传输将整个消息保存在内存缓冲区中,直到传输完成。
  •   
  • 流式传输仅缓冲邮件头并将邮件正文作为流公开,较小的部分可以从中流   一次阅读。
  •   

默认的TransferMode是Buffered,因此整个消息被加载到内存中。如果打开Streamed TransferMode,则可以通过编辑MaxBufferSize的值来管理内存使用的大小。

BinaryMessageEncoding反过来允许您压缩数据,通过网络发送。 以下是App.Config内容的示例

 <customBinding>
    <binding name="primaryBinding" openTimeout="00:01:00"  closeTimeout="00:01:00" 
              sendTimeout="00:30:00" receiveTimeout="00:30:00">
      <binaryMessageEncoding compressionFormat="GZip">
        <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                      maxArrayLength="2147483647" maxBytesPerRead="2147483647"
                      maxNameTableCharCount="2147483647" />
      </binaryMessageEncoding>
      <httpsTransport transferMode="Streamed" maxReceivedMessageSize="6000000" 
                      maxBufferSize="6000000" maxBufferPoolSize="12000000" />          
    </binding>      
  </customBinding>

代码中的相同配置

 private Binding GetBinding()
    {
        var config = new BindingElementCollection();            
        config.Add(new BinaryMessageEncodingBindingElement()
        {
            CompressionFormat = CompressionFormat.GZip,
        });
        config.Add(new HttpsTransportBindingElement()
        {
            MaxBufferPoolSize = 12000000,
            MaxBufferSize = 6000000,
            MaxReceivedMessageSize = 6000000,
            TransferMode = TransferMode.Streamed,
        });

        var resultBinding = new CustomBinding(config)
        {
            OpenTimeout = TimeSpan.FromMinutes(1),
            CloseTimeout = TimeSpan.FromMinutes(1),
            ReceiveTimeout = TimeSpan.FromMinutes(1),
            SendTimeout = TimeSpan.FromMinutes(1),
        };

        return resultBinding;
    }

答案 1 :(得分:1)

我从未尝试使用WCF发送超过50MB的内容,但我非常确定256MB +文件很容易导致上述问题,我建议您尝试以下方法:

  • 将文件剥离为较小的小块,例如每个文件50 MB
  • 在尝试发送文件时检查服务的内存分配,是否超出了计算机上可用内存的最大值?

答案 2 :(得分:1)

如前所述,我已将TransferMode更改为“Streamed”,但我也增加了最大缓冲区大小。将超时和maxAllowedContent增加到300mb,以允许上载更大的文件。现在效果很好。

答案 3 :(得分:1)

我知道它可能不适合所有人,但是......

我们最近遇到了类似的问题。在本地调试一些代码时,只有一个开发人员遇到了问题。原来他没有使用 64位版本的 IIS Express

答案 4 :(得分:0)

另见OutOfMemoryException while populating MemoryStream: 256MB allocation on 16GB system: 请求的内存逐步加倍,有些内存不能分配额外的内存 - 当你得到异常时就是这样。