2013-02-12 2 views
5

Я пытаюсь использовать именованные каналы для связи между сервером и клиентским процессом на одном компьютере. сервер отправляет сообщение клиенту, клиент что-то делает с ним и возвращает результат, а сервер должен получить результат.Дуплексная операция между двумя процессами с использованием именованных каналов в C#

вот код для сервера:

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.

В принципе, я не мог найти пример дуплекса named pipe в C#. Я либо нуждаюсь в этом, либо пример анонимной трубы, с двумя трубами для чтения, а другой для написания между родительским и дочерним процессом.

Спасибо заранее.

+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 .. 
} 

Как Johannes Egger указал, StreamWriter промывает поток на Dispose(), поэтому StreamWriter следует утилизировать первый и, таким образом, сам внутренний объект распоряжаться.

+0

Спасибо, что решил проблему. была еще одна проблема в коде, что Чтение происходило в цикле while, и в результате был тупик, изменил время на If, и теперь он отлично работает. – jambodev

+0

В моем случае было важно, чтобы писатель располагался после читателя, потому что писатель делал флеш, когда он был расположен, но когда читатель расположен сначала, труба также расположена, и писатель не может смываться. –

+0

@JohannesEgger хороший пункт. – TGlatzer