вопрос двунаправленной именованной трубы - PullRequest
2 голосов
/ 21 августа 2009

У меня есть 2 приложения, которые я хочу заставить общаться через именованные каналы в .NET 3.5. Это парадигма запрос / ответ, данные которой передаются в формате XML, чтобы облегчить мою жизнь. Есть приложение для прослушивания и приложение, которое отправляет запросы в канал. Я пытаюсь использовать двунаправленную трубу, чтобы сделать это. Проблема у меня заключается в том, что вызов StreamReader.ReadToEnd (), кажется, не возвращается. Что я могу сделать, чтобы это исправить?

Код слушателя

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(....);
    }  
}

Код запроса

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;
}

1 Ответ

6 голосов
/ 21 августа 2009

После того, как вы введете outstream.Write(xml.ToString()) в doIt(), вы затем попытаетесь прочитать с instream. Тем временем ваш другой поток ожидает в stream.ReadToEnd(). Он будет ждать вечно, потому что не знает, что ты закончил писать. Насколько он знает, вы могли бы очень хорошо позвонить outstream.Write() снова, чтобы записать еще немного данных. Вызов ReadToEnd() не вернется, пока вы фактически не закроете канал с doIt().

Вы можете обойти это, заставив их общаться немного более разумно. Вы можете, например, записать длину xml.ToString() в канал, а затем записать строку. Затем в своей ветке чтения вы сначала читаете длину, а затем читаете msg_in, читая только точное количество байтов, которое вы ожидаете отправить, останавливаясь, как только вы прочитаете их все, а не ожидая закрытия канала.

...