我正在研究启动一个进程,然后写入该进程的stdIn并从同一进程的stdOut读取的程序。
我的问题是,如果我没有大量数据要写入stdIn(例如1字节),则无法从stdOut获取数据,因为stdOut的ReadAsync
函数永远不会返回。
操作系统:Ubuntu 18.04 框架:dotnet核心2.2 语言:C#
这是我用来写到stdIn的代码:
public static async Task WriteToStdInAsync(
Stream input,
Stream stdIn
)
{
await Task.Yield();
byte[] buffer = new byte[1024 * 64];
int read;
while ((read = await input.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await stdIn.WriteAsync(buffer, 0, read);
}
await stdIn.FlushAsync();
}
我从大小为1个字节的“输入”流中读取,然后将数据传递到stdIn流。
然后我正试图以这种方式找回那个字节:
public static async Task ReadFromStdOutAsync(
Stream output,
Stream stdOut
)
{
await Task.Yield();
byte[] buffer = new byte[1024 * 64];
int read;
while ((read = await stdOut.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await output.WriteAsync(buffer, 0, read);
}
}
await stdOut.ReadAsync(buffer, 0, buffer.Length)
-在这种情况下永远不会返回。
如果我将输入流的大小增加到100KB(较少的值不起作用),则可以正常工作。如果在将所有数据发送到stdIn之后关闭stdIn流,它也适用于较小的大小。如您所见,我尝试刷新stdIn以强制进行数据传输,但是它不起作用。我认为操作系统中还有其他级别的缓冲,不允许stdOut看到数据。
这是我创建流程的方式:
return new Process() {
EnableRaisingEvents = false,
StartInfo = new ProcessStartInfo {
FileName = "python3",
Arguments = $"{Settings.PipesEchoServer}",
RedirectStandardOutput = true,
RedirectStandardInput = true,
UseShellExecute = false
},
};
我试图检查FileStream,Stream,Process的源代码,但找不到答案。
https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/Stream.cs https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/FileStream.cs https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/FileStream.Unix.cs https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs
感谢您的帮助。
编辑:
我通过这种方式获得信息流:
p.StandardInput.BaseStream,
p.StandardOutput.BaseStream,
其中p
是Process
类的实例
编辑2: 我想我找到了问题。我使用python脚本:
import sys
read = sys.stdin.buffer.read(1024)
while len(read) != 0:
sys.stdout.buffer.write(read)
sys.stdout.buffer.flush()
read = sys.stdin.buffer.read(1024 * 100)
,但是看起来sys.stdin.buffer.read
不会返回结果,除非所有1024个字节都从stdIn中变为红色。我将其更改为sys.stdin.buffer.read(1)
,现在可以使用了。
不确定btw这是在python中使用管道的最佳方法,但这是我发现如何传输二进制数据的最简单方法。
感谢GottZ提出阅读setvbuf
的建议