匿名管道 - 没有获取到所有数据

4

我将使用匿名管道在两个进程之间发送命令。通常情况下一切都很好,但有时消费者接收到的命令会被截断,只有一半传递过来。

这是我发送命令的方法:

AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out,     HandleInheritability.Inheritable);
StreamWriterpipeWriter = new StreamWriter(this.pipeServer) { AutoFlush = true };
pipeWriter.WriteLine(command);

这就是我阅读它们的方法:

AnonymousPipeClientStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, pipeId);
StreamReader pipeReader = new StreamReader(this.pipeClient);
string command = pipeReader.ReadLine();

该命令实际上是一个小的base64转换后的pdf文件,同时还含有一些额外的数据。将命令写入pipeWriter时,命令的格式是正确的(日志至少告诉我们这么多),而消费者收到的命令通常也是正确的。然而,偶尔会出现问题,消费者只能接收到部分命令。
当我们尝试重新发送相同的命令时,它会成功传输。重新发送命令将处理旧的消费者,但生产者将保持不变。
是否有任何已知原因导致此情况发生?我是否漏掉了一些显而易见的东西?
2个回答

4
在编写端,在关闭管道之前,您需要调用WaitForPipeDrain

为什么?我不想完全等待排水。 - wade
在我们的情况下,溢出的机会很低,而且实际上不需要等待...但是,在我们的错误情况下,这是否有任何影响呢? - wade
我遇到了和你类似的问题 - 添加 WaitForPipiDrain 解决了它。 - user2126375
糟糕...我们特意移除了WaitForPipeDrain,以为在StreamWriter中设置AutoFlush就可以完成其工作。我不确定我们是否能够实现这一点。不过我将尝试测试它,并让你知道结果。 - wade
作者必须在关闭管道之前调用它。足够接近了。 - Hans Passant
显示剩余2条评论

3
这是Windows管道实现中的一个怪癖。 它不能区分“我关闭了管道,因为出了问题”和“我关闭了管道,因为我用完了”。它实现了前者,丢弃了缓冲区中的数据,因此需要编写者在关闭管道之前明确确保存储在管道缓冲区中的数据已传递给客户端。本机winapi函数是FlushFileBuffers()。
.NET包装类可能会使这个清晰一些,但它们没有。 因此,您还必须明确说明,在匿名管道服务器流关闭之前调用FlushFileBuffers()函数需要调用WaitForPipeDrain()。 当由于异常而关闭管道时不要这样做。

非常好的回答。谢谢! - wade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接