views:

432

answers:

1

I have 2 apps that I want to make communicate via named pipes on .NET 3.5. Its a request/response paradigm, with the data transmitted as XML to make my life easier. There is a listener app, and an app that posts requests to the pipe. I'm trying to use a bidirectional pipe to do this. The problem i have is that the call to StreamReader.ReadToEnd() doesnt seem to return. What can I do to fix this?

Listener code

public Class Listener
{
    private void ThreadFunc()
    {
       var pipe = new NamedPipeServerStream("GuideSrv.Pipe",PipeDirection.InOut);
       var instream = new StreamReader(pipe);
       var outstream = new StreamWriter(pipe);
       while (true)
       {
           pipe.WaitForConnection();
           var response = ProcessPipeRequest(instream);
           outstream.Write(response.ToString());
           pipe.Disconnect();
       }
    }
    private XDocument ProcessPipeRequest(StreamReader stream)
    {
        var msg_in = stream.ReadToEnd();  // << This call doesnt return
        var xml_in = XDocument.Parse(msg_in);
        // do some stuff here 
        return new XDocument(....);
    }  
}

Requester code

public XDocument doIt()
{
    var xml = new XDocument(....);
    using (var pipe = new NamedPipeClientStream(".", "GuideSrv.Pipe", PipeDirection.InOut))
     {
        using (var outstream = new StreamWriter(pipe))
        using (var instream = new StreamReader(pipe))
        {
            pipe.Connect();
            outstream.Write(xml.ToString());
            xml = XDocument.Parse(instream.ReadToEnd());
        }
    }
    return xml;
}
+2  A: 

After you do outstream.Write(xml.ToString()) in doIt() you then try to read from instream. Meanwhile your other thread is waiting in stream.ReadToEnd(). It will wait forever because it doesn't know that you're done writing. As far as it knows you could very well call outstream.Write() again to write some more data. The ReadToEnd() call is not going to return until you actually close the pipe from doIt().

You can work around this by making them communicate with each other a little bit more intelligently. You could, for example, write the length of xml.ToString() to the pipe and then write the string. Then in your reader thread you first read the length and then read msg_in, only reading exact number of bytes you expect to be sent, stopping as soon as you read them all rather than waiting for the pipe to be closed.

John Kugelman