【问题标题】:System.IO.Exception: Pipe is brokenSystem.IO.Exception:管道损坏
【发布时间】:2010-10-28 01:59:37
【问题描述】:

我有两个通过命名管道相互通信的 .NET 应用程序。第一次一切都很好,但是在发送第一条消息之后,服务器将再次侦听,WaitForConnection() 方法抛出 System.IO.Exception 消息 Pipe is broken.
为什么我在这里得到这个异常?这是我第一次使用管道,但过去使用套接字的类似模式也适用于我。

代码啊!
服务器:

using System.IO.Pipes;

static void main()
{
    var pipe = new NamedPipeServerStream("pipename", PipeDirection.In);
    while (true)
    {
        pipe.Listen();
        string str = new StreamReader(pipe).ReadToEnd();
        Console.Write("{0}", str);
    }
}

客户:

public void sendDownPipe(string str)
{
    using (var pipe = new NamedPipeClientStream(".", "pipename", PipeDirection.Out))
    {
        using (var stream = new StreamWriter(pipe))
        {
            stream.Write(str);
        }
    }
}

对 sendDownPipe 的第一次调用让服务器打印我发送的消息就好了,但是当它循环回来再次收听时,它便便。

【问题讨论】:

  • 我认为您遇到此问题的原因是因为“new StreamReader(pipe)”行。创建的流阅读器的范围是第一个 while 循环,然后重新创建它。但是,流读取器的行为是关闭它们正在包装的流 - 因此一旦超出范围,它将关闭管道流。您可以尝试将其声明移出 while 循环并检查(PS:如果您这样做,我没有亲自尝试代码是否有效 - 只是想添加评论而不是回答)

标签: c# .net-3.5 named-pipes


【解决方案1】:

我将发布我的似乎可以工作的代码 - 我很好奇,因为我从未对管道做过任何事情。我在相关命名空间中没有找到你为服务器端命名的类,所以这里是基于 NamedPipeServerStream 的代码。回调的东西只是因为我不能为两个项目而烦恼。

NamedPipeServerStream s = new NamedPipeServerStream("p", PipeDirection.In);
Action<NamedPipeServerStream> a = callBack;
a.BeginInvoke(s, ar => { }, null);
...
private void callBack(NamedPipeServerStream pipe)
{
  while (true)
  {
    pipe.WaitForConnection();
    StreamReader sr = new StreamReader(pipe);
    Console.WriteLine(sr.ReadToEnd());
    pipe.Disconnect();
  }
}

客户端会这样做:

using (var pipe = new NamedPipeClientStream(".", "p", PipeDirection.Out))
using (var stream = new StreamWriter(pipe))
{
  pipe.Connect();
  stream.Write("Hello");
}

我可以在服务器运行的情况下多次重复上面的块,没有问题。

【讨论】:

  • 成功了。我猜当客户端从另一端掉下来时,没有隐式断开连接。谢谢。
  • 这对我也有帮助。感谢您的精彩回答!
  • 这给了我一个管道没有连接到这条线上的错误:using (var stream = new StreamWriter(pipe))
  • 似乎在进程之间不起作用。 pipe.Disconnect() 因“无法访问封闭的管道”而爆炸
  • @Sean,当您的 StreamWriter 被 using() 处理时,底层管道也将关闭。您可以通过使用 new StreamWriter(pipe, Encoding.UTF8, -1, true) 创建 StreamWriter 来避免这种情况。您需要创建具有类似重载的阅读器。
【解决方案2】:

在客户端断开连接后,我从服务器调用 pipe.WaitForConnection() 时出现了问题。解决方法是捕获IOException并调用pipe.Disconnect(),然后再次调用pipe.WaitForConnection():

while (true)
{
    try
    {
        _pipeServer.WaitForConnection();
        break;
    }
    catch (IOException)
    {
        _pipeServer.Disconnect();
        continue;
    }            
 }

【讨论】:

    【解决方案3】:

    我遇到了同样的问题 - 它是由 Using...End Using 处理服务器的 StreamReader 引起的,这也取消了 NamedPipeServerStream。解决方案就是不要使用...结束使用它并信任垃圾收集器。

    【讨论】:

    • 如果您不使用using,请考虑使用Dispose()。希望 GC 释放内存是一种不好的方法。