2013-02-12 22 views
5

名前付きパイプを使用して、同じマシン上のサーバープロセスとクライアントプロセス間の通信を試みています。サーバーはクライアントにメッセージを送り、クライアントはそれに何かをして結果を返し、サーバーは結果を受け取ることになっています。ここCで名前付きパイプを使用する2つのプロセス間のデュプレックス操作

は、サーバーのコードです:

using System; 
using System.IO; 
using System.IO.Pipes; 

class PipeServer 
{ 
    static void Main() 
    { 
     using (NamedPipeServerStream pipeServer = 
      new NamedPipeServerStream("testpipe", PipeDirection.InOut)) 
     { 
      Console.WriteLine("NamedPipeServerStream object created."); 

      // Wait for a client to connect 
      Console.Write("Waiting for client connection..."); 
      pipeServer.WaitForConnection(); 

      Console.WriteLine("Client connected."); 
      try 
      { 
       // Read user input and send that to the client process. 
       using (StreamWriter sw = new StreamWriter(pipeServer)) 
       { 
        sw.AutoFlush = true; 
        Console.Write("Enter text: "); 
        sw.WriteLine(Console.ReadLine()); 
       } 

       pipeServer.WaitForPipeDrain(); 

       using (StreamReader sr = new StreamReader(pipeServer)) 
       { 
        // Display the read text to the console 
        string temp; 

        // Wait for result from the client. 
        while ((temp = sr.ReadLine()) != null) 
        { 
         Console.WriteLine("[CLIENT] Echo: " + temp); 
        } 
       } 

      } 
      // Catch the IOException that is raised if the pipe is 
      // broken or disconnected. 
      catch (IOException e) 
      { 
       Console.WriteLine("ERROR: {0}", e.Message); 
      } 
     } 
    } 
} 

、ここでは、クライアントのコードです:

using System; 
using System.IO; 
using System.IO.Pipes; 

class PipeClient 
{ 
    static void Main(string[] args) 
    { 
     using (NamedPipeClientStream pipeClient = 
      new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut)) 
     { 

      // Connect to the pipe or wait until the pipe is available. 
      Console.Write("Attempting to connect to pipe..."); 
      pipeClient.Connect(); 

      Console.WriteLine("Connected to pipe."); 
      Console.WriteLine("There are currently {0} pipe server instances open.", 
       pipeClient.NumberOfServerInstances); 
      using (StreamReader sr = new StreamReader(pipeClient)) 
      { 
       // Display the read text to the console 
       string temp; 
       while ((temp = sr.ReadLine()) != null) 
       { 
        Console.WriteLine("Received from server: {0}", temp); 
       } 
      } 


      // send the "result" back to the Parent process. 
      using (StreamWriter sw = new StreamWriter(pipeClient)) 
      { 
       sw.AutoFlush = true; 
       sw.WriteLine("Result"); 
      } 

      pipeClient.WaitForPipeDrain(); 

     } 
     Console.Write("Press Enter to continue..."); 
     Console.ReadLine(); 
    } 
} 

しかし、サーバコードで、行pipeServer.WaitForPipeDrain()で。 ObjectDisposedExceptionが発生し、「閉じたパイプにアクセスできません」と表示されます。

sw.AutoFlushをtrueに設定すると、クライアントコードでも同じエラーが発生します。

基本的には、C#で二重の名前付きパイプの例が見つかりませんでした。私はそれを必要とするか、または無関係なパイプの例を必要とします。これは、読み取り用のパイプと親プロセスと子プロセスの間の書き込み用のパイプの2つです。

ありがとうございました。

+1

'StreamWriter'を破棄しても、元のストリーム(つまり、あなたの' pipeServer')も閉じないでしょうか? –

+0

名前付きパイプの上を走っているWCFは、大量の作業を節約します。 –

+0

ここで例をご覧ください。 – jambodev

答えて

7

問題はStreamWriterのブロックを使用しています。これは、下にあるストリーム(ここではあなたのパイプです)を閉じます。あなたがそのブロックを使用しない場合、それは動作するはずです。

次の操作を行うことができます:

using (var pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut)) 
using (var streamReader = new StreamReader(pipeServer)) 
using (var streamWriter = new StreamWriter(pipeServer)) 
{ 
    // ... Your code .. 
} 

ヨハネス・エッガーが指摘したように、StreamWriterDispose()上のストリームをフラッシュし、そのStreamWriterが最初に配置されたため、処分する最も内側のオブジェクトであるべきです。

+0

ありがとう、それは問題を解決しました。コードにもう1つの問題がありました。読み取りがwhileループで行われていたため、デッドロックが発生し、whileをIfに変更しました。 – jambodev

+0

私の場合、ライターが廃棄されたときにライターが落ちたので、ライターが後に配置されることが重要でしたが、リーダーが最初に配置されたときにパイプも廃棄され、ライターはフラッシュできません。 –

+0

@JohannesEgger良い点。 – TGlatzer

関連する問題