C# – How to continue sending/reading messages from named pipes / streams

cnamed-pipesnetstream

I'm teaching myself to use pipes and I have two apps, one with the PipeServer class and one with the PipeClient class (shown below). The server app creates an instance of the PipeServer and has a text box that calls the WriteMessage method when the text box changes. The client app creates an instance of the PipeClient, sets the MessageReadEvent to a method that fills in a textbox with the given message, and then calls the ReadMessages method.

The first time the ReadMessages method is called it gets to the sr.ReadLine() and waits there until a message is received. After a message is received the next call to sr.ReadLine() naturally returns null and it continues to exit the method.

At this point, any further calls to ReadMessages gives me an exception saying the pipe is closed. I'm not sure I understand why the pipe is getting closed. How do I keep it open? Surely I don't have to create a new instance of a pipe for every message I want to send?

Below is my PipeClient class. I can add my PipeServer class too if it would be helpful, but I think the issue is located in here…

    public delegate void MessageReadEventHandler(string message);

    class PipeClient: IDisposable
    {
        public event MessageReadEventHandler MessageReadEvent;

        NamedPipeClientStream _pipeClient;

        public PipeClient(string pipeName)
        {
            _pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.In);
            _pipeClient.Connect();
        }

        public void ReadMessages()
        {
            string temp;

            // Is _pipeClient getting disposed when sr gets disposed??
            // I wouldn't think so but I don't understand why I can't seem
            // to use it again after the following using statement is run

            using (StreamReader sr = new StreamReader(_pipeClient))
                while ((temp = sr.ReadLine()) != null)
                    if(MessageReadEvent != null)
                        MessageReadEvent(temp);
        }

        public void Dispose()
        {
            _pipeClient.Dispose();
        }
    }

Best Answer

StreamReader closes stream passed to it after disposal, and you are disposing StreamReader in the end of using (StreamReader sr = new StreamReader(_pipeClient)) block.

You can create StreamReader at class level in constructor, and use it in ReadMessages method

  public PipeClient(string pipeName)
    {
        _pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.In);
        _pipeClient.Connect();
        _streamReader = new StreamReader(_pipeClient);
    }
  public void ReadMessages()
    {
        string temp;



            while ((temp = _streamReader.ReadLine()) != null)
                if(MessageReadEvent != null)
                    MessageReadEvent(temp);
    }