2013-01-23 10 views
18

現在、WCFセルフサービス(IISなし)を使用して大量のデータを送信しようとすると、問題が発生しています。 私のサービスがSystem.OutOfMemoryExceptionでクラッシュした状態で、ストリーミング結果を使用して500MBを転送しています。 このような量のデータを転送することは可能ですか?ここでWCF自己ホスト型サービスで大きなデータ(500MB/1GB)をストリーミングする

は私のWCFの設定です:

<system.serviceModel> 
<services> 
    <service name="CIService" behaviorConfiguration="CIBehavior">   
    <host> 
     <baseAddresses> 
     <add baseAddress="net.tcp://localhost:6547/CIService/CIService.svc" /> 
     </baseAddresses> 
    </host> 
    <endpoint binding="netTcpBinding" 
     bindingConfiguration="netTcpBindingConfig" 
     behaviorConfiguration="CIBehavior.EndpointBehavior" 
     contract="CIService.ICreatable" /> 
    <endpoint address="mex" 
     binding="mexHttpBinding" 
     name="mexTcpBinding" 
     contract="IMetadataExchange" /> 
    </service> 
</services> 
<serviceHostingEnvironment multippleSiteBindingEnabled="True" /> 
<bindings> 
    <netTcpBinding> 
    <binding name="netTcpBindingConfig" closeTimeout="00:01:00" openTimeout="00:01:00" 
     receiveTimeout="01:00:00" sendTimeout="00:10:00" 
     hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxConnections="10" 
     maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" 
     transferMode="Streamed"> 
     <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" 
     maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
    </binding> 
    </netTcpBinding> 
</bindings> 

<behaviors> 
    <serviceBehaviors> 
    <behavior name="CIBehavior"> 
     <serviceMetadata httpGetEnabled="False" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
     <serviceThrottling maxConcurrentCalls="200" maxConcurrentInstances="2147483647" maxConcurrentSessions="100" /> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
    </behavior> 
    </serviceBehaviors> 
    <endpointBehavior> 
    <behavior name="CIBehavior.EndpointBehavior"> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
    </behavior> 
    </endpointBehavior> 
</behaviors> 
</system.serviceModel> 

私のクライアントの設定:

<system.serviceModel> 
<bindings> 
    <netTcpBinding> 
    <binding name="NetTcpBinding_ICreatable" 
      closeTimeout="00:01:00" openTimeout="00:01:00" 
      receiveTimeout="01:00:00" sendTimeout="00:10:00" 
      transactionFlow="false" 
      transferMode="Streamed" 
      transactionProtocol="OleTransactions" 
      hostNameComparisonMode="StrongWildcard" 
      listenBacklog="10" 
      maxBufferPoolSize="2147483647" 
      maxBufferSize="2147483647" 
      maxConnections="10" 
      maxReceivedMessageSize ="2147483647"> 
     <readerQuotas 
     maxDepth="2147483647" 
     maxStringContentLength="2147483647" 
     maxArrayLength="2147483647" 
     maxBytesPerRead="2147483647" 
     maxNameTableCharCount="2147483647" /> 
     <reliableSession ordered="true" inactivityTimeout="00:10:00" anabled="false" /> 
    </binding> 
    </netTcpBinding> 
</bindings> 
<client> 
    <endpoint name="NetTcpBinding_ICreatable" 
     address="net.tcp://localhost:6547/CIService/CIService.svc" 
     binding="netTcpBinding" 
     bindingConfiguration="NetTcpBinding_ICreatable" 
     behaviorConfiguration="CIBehavior.EndpointBehavior" 
     contract="ICreatable" /> 
</client> 
<behaviors> 
    <endpointBehavior> 
    <behavior name="CIBehavior.EndpointBehavior"> 
     <dataContractSerializer maxItemsInObjectGraph="2147483647" /> 
    </behavior> 
    </endpointBehavior> 
</behaviors> 
</system.serviceModel> 
+1

データをより小さな部分にチャンクする必要があります。 – TGlatzer

+0

大きなメッセージを転送することは間違いありません。このhttp://orand.blogspot.fr/2007/12/wcf-message-size-tester.htmlを参照してください。 –

答えて

35

あなたはmaxBufferPoolSizeが、これらはおそらくメモリ不足の例外のあなたのアウトを引き起こしているので、高く設定のMaxBufferSizeまたはを必要といけません。デフォルトは正常です。大規模データテキストのこの作品のために、MSDNの

チェックアウトLarge Data and Streaming、特にセクション特別なセキュリティに関する考慮事項のMaxBufferSizeプロパティがメモリその WCFバッファを拘束するために必要とされる

重要です。ストリーミングするときは、これを安全な値に設定するか(またはデフォルト値のままにすることが重要です)(または )たとえば、 サービスで最大4 GBのファイルを受信し、ローカルディスク に保存する必要があるとします。 のようにメモリが制限されていると仮定すると、一度に64 KBのデータしかバッファできません。次に、 をMaxReceivedMessageSizeを4GBに、MaxBufferSizeを64KBに設定します。また、サービスの実装で を使用する場合は、64 KBのチャンクで入ってくるストリームから のみを読み込み、次の チャンクを読み取らずに、前のディスクをディスクに書き込んだ後、メモリから を破棄する必要があります。

私は、自己ホスト型サービスからコンソールクライアントにデータをストリーミングする非常に簡単な例をまとめました。ポストを短くするために、私はサーバーコードとクライアントの一部だけを追加しました。

サービス契約

using System.IO; 
using System.ServiceModel; 

namespace Service 
{ 
    [ServiceContract] 
    public interface IStream 
    { 
     [OperationContract] 
     Stream GetLargeObject(); 
    } 
} 

サービスの実装

using System; 
using System.IO; 
using System.ServiceModel; 

namespace Service 
{ 
    [ServiceBehavior] 
    public class StreamService : IStream 
    { 
     public Stream GetLargeObject() 
     { 
      // Add path to a big file, this one is 2.5 gb 
      string filePath = Path.Combine(Environment.CurrentDirectory, "C:\\Temp\\BFBC2_PC_Client_R11_795745_Patch.exe"); 

     try 
     { 
      FileStream imageFile = File.OpenRead(filePath); 
      return imageFile; 
     } 
     catch (IOException ex) 
     { 
      Console.WriteLine(String.Format("An exception was thrown while trying to open file {0}", filePath)); 
      Console.WriteLine("Exception is: "); 
      Console.WriteLine(ex.ToString()); 
      throw; 
     } 
    } 
} 
} 

サービス

メイン
using System; 
using System.ServiceModel; 

namespace Service 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       using (var serviceHost = new ServiceHost(typeof(StreamService))) 
       { 
        serviceHost.Open(); 

        Console.WriteLine("Press Any Key to end"); 
        Console.ReadKey(); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 
    } 
} 

サービスのapp.config

<?xml version="1.0"?> 
<configuration> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 

    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="StreamServiceBehavior"> 
      <serviceMetadata httpGetEnabled="True" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <netTcpBinding> 
     <binding name="NewBinding0" transferMode="Streamed"/> 
     </netTcpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="StreamServiceBehavior" name="Service.StreamService"> 
     <endpoint address="net.tcp://localhost:9000/streamserver" binding="netTcpBinding" 
      bindingConfiguration="NewBinding0" bindingName="" contract="Service.IStream" /> 
     <endpoint address="mex" binding="mexHttpBinding" 
      contract="IMetadataExchange" /> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:8080/StreamService" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    </system.serviceModel> 
</configuration> 

サービスを起動します。ソケットを開くには管理者アカウントで実行する必要があります。クライアントコンソールアプリケーションを作成し、url http:// localhost:8080/StreamServiceを使用してService Referenceを追加し、生成されたクライアントのネームスペースとしてServiceを使用します。

using System; 
using System.IO; 
using Client.Service; 

namespace Client 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       using (StreamClient streamClient = new StreamClient()) 
       { 
        streamClient.Open(); 

        using (FileStream fileStream = new FileStream("c:\\temp\\bigfile.exe",FileMode.Create)) 
        { 
         streamClient.GetLargeObject().CopyTo(fileStream);  
        } 
       } 

       Console.WriteLine("Press any key to end"); 
       Console.ReadKey(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex); 
      } 
     } 
    } 
} 

生成されたクライアントの設定ファイルがわずかに変更する必要があります主なクライアントは、maxReceivedMessageSize = "4294967295"

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
      <binding name="NetTcpBinding_IStream" closeTimeout="00:01:00" 
       openTimeout="00:01:00" receiveTimeout="00:30:00" sendTimeout="00:01:00" 
       transactionFlow="false" transferMode="Streamed" transactionProtocol="OleTransactions" 
       hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
       maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" 
       maxReceivedMessageSize="4294967295"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
        enabled="false" /> 
       <security mode="Transport"> 
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
        <message clientCredentialType="Windows" /> 
       </security> 
      </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://localhost:9000/streamserver" binding="netTcpBinding" 
      bindingConfiguration="NetTcpBinding_IStream" contract="Service.IStream" 
      name="NetTcpBinding_IStream"> 

     </endpoint> 
    </client> 
</system.serviceModel> 

打ち上げサービスreceivetimeoutの増加と設定クライアント。大きなファイルを問題なくストリーミングします。

関連する問題