我试图通过WCF服务调用将一些大数据保存到数据库.我无法调用该服务.它抛出一个错误:
无法分配268435456字节的托管内存缓冲区.可用内存量可能很低
public async Task<int> UploadExportPackage(DTO.Upload.UploadPackage package)
{
int result = await serviceProxy.UploadResultsAsync(package);
return result;
}
Run Code Online (Sandbox Code Playgroud)
服务器端配置:
<!--
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>
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
Exception no: 0
Run Code Online (Sandbox Code Playgroud)
下一个例外:消息:
无法分配268435456字节的托管内存缓冲区.可用内存量可能很低.
堆栈跟踪:服务器堆栈跟踪:在System.Runtime.Fx.AllocateByteArray(的Int32大小)在System.Runtime.InternalBufferManager.PooledBufferManager.TakeBuffer(的Int32缓冲区大小)在System.ServiceModel.Channels.BufferManagerOutputStream.Init(的Int32 INITIALSIZE,的Int32 maxSizeQuota, INT32 effectiveMaxSize,BufferManager bufferManager)在System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(消息消息,BufferManager bufferManager,INT32 initialOffset,INT32 maxSizeQuota)在System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(消息消息,INT32 maxMessageSize,BufferManager bufferManager ,System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(消息消息,布尔值为shouldRecycleBuffer)处于System.ServiceModel.Cn上的System.ServiceModel.Channels.HttpOutput.SendAsyncResult.SendWithoutChannelBindingToken()处于System.ServiceModel.Channels.HttpOutput.SendAsyncResult.Send()处System.ServiceModel.Channels.HttpOutput.SendAsyncResult..ctor(高程 tpOutput httpOutput,HttpResponseMessage httpResponseMessage,布尔suppressEntityBody在System.ServiceModel.Channels.HttpChannelFactory,时间跨度超时回调的AsyncCallback,对象状态)在System.ServiceModel.Channels.HttpOutput.BeginSendCore(HttpResponseMessage httpResponseMessage,时间跨度超时回调的AsyncCallback,对象状态)1.HttpRequestChannel.HttpChannelAsyncRequest.SendWebRequest()
at System.ServiceModel.Channels.HttpChannelFactory1 System.ServiceModel.Channels.SecurityChannelFactory上的System.ServiceModel.Channels.RequestChannel.BeginRequest(消息消息,TimeSpan超时,AsyncCallback回调,对象状态)中的.HttpRequestChannel.HttpChannelAsyncRequest.BeginSendRequest(消息消息,TimeSpan超时)1.RequestChannelSendAsyncResult.BeginSendCore(IRequestChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, Object state)
at System.ServiceModel.Security.ApplySecurityAndSendAsyncResult1.OnSecureOutgoingMessageComplete(消息消息) )在System.ServiceModel.Security.ApplySecurityAndSendAsyncResult 1.Begin(Message message, SecurityProtocolCorrelationState correlationState)
at System.ServiceModel.Channels.SecurityChannelFactory1.SecurityRequestChannel.BeginRequest(消息消息,时间跨度超时回调的AsyncCallback,对象状态)在System.ServiceModel.Dispatcher.RequestChannelBinder.BeginRequest(消息消息,时间跨度超时回调的AsyncCallback,对象统计 e)System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartSend(Boolean completedSynchronously)在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.StartEnsureOpen的System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.FinishEnsureOpen(IAsyncResult result,Boolean completedSynchronously)中的System.ServiceModel.Channels.ServiceChannel.布局completedSynchronously)在System.ServiceModel.CandishEnsureInteractiveInit(IAsyncResult result,Boolean completedSynchronously)System.ServiceModels.Channel.SendAsyncResult.StartEnsureInteractiveInit()at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.Begin()在System.ServiceModel.Channels.ServiceChannel.BeginCall在System.ServiceModel.Channels.ServiceChannel.BeginCall(ServiceChannel通道,ProxyOperationRuntime操作(字符串动作,布尔单向,ProxyOperationRuntime操作,对象[]插件,时间跨度超时回调的AsyncCallback,对象asyncState) ,Object [] ins,AsyncCallback cal lback,在System.Threading.Tasks.TaskFactory对象asyncState)1.FromAsyncImpl[TArg1,TArg2,TArg3](Func6 beginMethod,Func键2 endFunction, Action1个endAction,TArg1 ARG1,TArg2 ARG2,TArg3 ARG3,在System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.CreateGenericTask对象状态,TaskCreationOptions creationOptions)[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(即时聊天消息)
在异常重新抛出[0]:在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(即时聊天reqMsg,即时聊天retMsg)处RossendaleClient8.DAL System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&MSGDATA,的Int32类型).位于RossendaleClient8.DAL.RossendaleServiceClient.d__13.MoveNext()的RossendaleClient8.DAL.RR.RossendaleServiceClient.UploadResultsAsync(UploadPackage包)中的RR.IRossendaleService.UploadResultsAsync(UploadPackage包)
下一个例外:消息:
抛出了类型'System.OutOfMemoryException'的异常.
堆栈跟踪:在System.Runtime.Fx.AllocateByteArray(Int32大小)
如果您的绑定允许,请尝试使用TransferMode.Streamed.您还可以查看BinaryMessageEncoding.来自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>
Run Code Online (Sandbox Code Playgroud)
代码中的配置相同
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;
}
Run Code Online (Sandbox Code Playgroud)
如前所述,我已将 TransferMode 更改为“Streamed”,但我还增加了最大缓冲区大小。将超时和 maxAllowedContent 增加到 300mb,以允许上传更大的文件。现在效果很好。