お世話になっております。
行いたいこと
同一PC内で2つのソフトウェア間でbyte配列の受け渡しを行いたいと思っています。
クライアント側から要求があった際にホスト側からbyte配列を送信する仕様にしたいと思っています。
配列の大きさは最大11,059,200byteを予定しています。
問題点
大量のデータを送信しようすると下記のようなエラーが出力されます。
最後にソースコードを記載しています。
エラー
Host
クラスのcallback.SendByteArr(arr);
にて
System.ServiceModel.CommunicationException: 'パイプ パイプを閉じています。 (232, 0xe8) への書き込みエラーが発生しました。'
内部例外
PipeException: パイプ パイプを閉じています。 (232, 0xe8) への書き込みエラーが発生しました。
試したこと
エラー内容で調べたところ帯域不足の可能性があるなどの情報が得られたので
構成エディター ツール (SvcConfigEditor.exe)でソースコード>App.configのように帯域の値を大きくしてみました。このページなどを参考にしました。
→ 同じエラーが出力される
Host側のarrのサイズ変更
(1) var arr = new byte[500];
→ ○
(2) var arr = new byte[65000];
→ ○
(3) var arr = new byte[65500];
→ ×
上記の(3)よりデフォルトの帯域最大値である65535より小さい値でも同一のエラーが出力されることが分かりました。
これにより帯域以外に原因があるのではと考えました。
質問
・エラーの原因・解決策などありましたら教示いただけないでしょうか。
・また、WCF以外にプロセス間で大量データをやりとりする手法があれば教えて頂ければ幸いです。
ソースコード
C#
1 // サーバー・クライアント共通インターフェース 2 [ServiceContract(CallbackContract = typeof(ICallback))] 3 internal interface IHost 4 { 5 [OperationContract(IsOneWay = true)] 6 void ByteArrRequest(); 7 } 8 9 [ServiceContract] 10 internal interface ICallback 11 { 12 [OperationContract(IsOneWay = true)] 13 void SendByteArr(byte[] bs); 14 }
C#
1 // ホスト側 2 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)] 3 public class Host : IHost 4 { 5 public void ByteArrRequest() 6 { 7 Console.WriteLine("[HOST]: CLIENTから要求あり"); 8 9 var callback = OperationContext.Current.GetCallbackChannel<ICallback>(); 10 11 var arr = new byte[65500]; 12 callback.SendByteArr(arr); // ★ここでエラーが出力される 13 } 14 } 15 16 ServiceHost sh; 17 public MainWindow() 18 { 19 InitializeComponent(); 20 21 const string addr = "net.pipe://localhost/test1"; 22 var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); 23 // 追記1(解決策) 24 binding.MaxReceivedMessageSize = 64000000; 25 binding.MaxBufferSize = 64000000; 26 var readerQuotas = new XmlDictionaryReaderQuotas(); 27 readerQuotas.MaxArrayLength = 64000000; 28 readerQuotas.MaxStringContentLength = 64000000; 29 readerQuotas.MaxDepth = 32; 30 binding.ReaderQuotas = readerQuotas; 31 // 追記1ここまで 32 sh = new ServiceHost(typeof(Host)); 33 sh.AddServiceEndpoint(typeof(IHost), binding, addr); 34 sh.Open(); 35 }
C#
1 // クライアント側 2 class Callback : ICallback 3 { 4 public void SendByteArr(byte[] message) 5 { 6 Console.WriteLine(message.Length); 7 } 8 } 9 10 public MainWindow() 11 { 12 InitializeComponent(); 13 14 const string addr = "net.pipe://localhost/test1"; 15 var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); 16 // 解決策 17 binding.MaxReceivedMessageSize = 64000000; 18 binding.MaxBufferSize = 64000000; 19 var readerQuotas = new XmlDictionaryReaderQuotas(); 20 readerQuotas.MaxArrayLength = 64000000; 21 readerQuotas.MaxStringContentLength = 64000000; 22 readerQuotas.MaxDepth = 32; 23 binding.ReaderQuotas = readerQuotas; 24 // 解決策ここまで 25 var host = DuplexChannelFactory<IHost>.CreateChannel(new InstanceContext(new Callback()), binding, new EndpointAddress(addr)); 26 27 host.ByteArrRequest(); 28 }
↓ App.config(ホスト・クライアント共に同一内容)
XAML
1 <system.serviceModel> 2 <bindings> 3 <netNamedPipeBinding> 4 <binding name="NewBinding0" closeTimeout="00:20:00" openTimeout="00:20:00" 5 receiveTimeout="00:20:00" sendTimeout="00:20:00" maxBufferSize="64000000" 6 maxReceivedMessageSize="64000000"> 7 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="64000000" 8 maxBytesPerRead="64000000" /> 9 </binding> 10 </netNamedPipeBinding> 11 </bindings> 12 <behaviors> 13 <endpointBehaviors> 14 <behavior name="NewBehavior0"> 15 <dataContractSerializer maxItemsInObjectGraph="10000000" /> 16 </behavior> 17 </endpointBehaviors> 18 <serviceBehaviors> 19 <behavior name="MyBehavior"> 20 <dataContractSerializer maxItemsInObjectGraph="100000000" /> 21 <serviceMetadata httpGetEnabled="true" /> 22 <serviceDebug includeExceptionDetailInFaults="true" /> 23 </behavior> 24 </serviceBehaviors> 25 </behaviors> 26 </system.serviceModel>
環境
C# .Net F/W 4.6.1
WPF
回答1件
あなたの回答
tips
プレビュー