C# 输入数据不足时,标准数据管道不刷新?
我正在编写一个程序,该程序启动一个进程,然后写入进程的stdIn并从同一进程的stdOut读取 我的问题是,如果我没有大的数据集要写入stdIn,例如1字节,我就无法从stdOut获取数据,因为stdOut的C# 输入数据不足时,标准数据管道不刷新?,c#,linux,.net-core,C#,Linux,.net Core,我正在编写一个程序,该程序启动一个进程,然后写入进程的stdIn并从同一进程的stdOut读取 我的问题是,如果我没有大的数据集要写入stdIn,例如1字节,我就无法从stdOut获取数据,因为stdOut的ReadAsync函数永远不会返回 操作系统:Ubuntu 18.04 框架:dotnetcore2.2 语言:C# 下面是我用来编写stdIn的代码: public static async Task WriteToStdInAsync( Stream input,
ReadAsync
函数永远不会返回
操作系统:Ubuntu 18.04
框架:dotnetcore2.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);
}
}
p.StandardInput.BaseStream,
p.StandardOutput.BaseStream,
等待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的源代码,但找不到答案
谢谢你的帮助
编辑:
我是这样得到的:
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);
}
}
p.StandardInput.BaseStream,
p.StandardOutput.BaseStream,
其中,p
是过程
类的一个实例
编辑2:
我想我发现了问题所在。我使用python脚本:
导入系统
read=sys.stdin.buffer.read(1024)
而len(read)!=0:
sys.stdout.buffer.write(read)
sys.stdout.buffer.flush()
read=sys.stdin.buffer.read(1024*100)
但是看起来,sys.stdin.buffer.read在stdin的所有1024字节都变为红色之前不会返回结果。我将它改为sys.stdin.buffer.read(1)
,现在它可以工作了
顺便说一句,我不确定这是在python中使用管道的最佳方式,但这是我发现的传输二进制数据的最简单方式
感谢GottZ提供的有关
setvbuf
的信息,csetvbuf中有一个设置io缓冲类型的函数(stdout,NULL,_IOLBF,0)
如果你能在c#中使用它,你可能想检查一下。该行将标准输出设置为行缓冲。也许可以更仔细地看看您使用setvbuf
的选项,我调用了一个python脚本,它使用sys.stdout.buffer
将数据重定向到stdout。我使用它,因为我还没有找到更好的方法将二进制数据从stdin传输到stdout。我将从sys.stdin.buffer.read(1024*100)
读取缓冲区的方式更改为sys.stdin.buffer.read(1)
,这很有帮助。看起来,sys.stdin.buffer.read
在获得所有字节数之前不会返回值。这是一个缓冲管道。总是。很高兴看到你找到了解决办法。如果你想有一个自定义的协议,你可以添加一个小的报头,它会告诉你下一个readhaving报头会带来多少数据,这是一个好主意,当我从这个POC移动到真正的程序时,我会记住它。非常感谢:)在csetvbuf中有一个设置io缓冲类型的函数(stdout,NULL,_IOLBF,0)
如果你能在c#中使用它,你可能想检查一下。该行将标准输出设置为行缓冲。也许可以更仔细地看看您使用setvbuf
的选项,我调用了一个python脚本,它使用sys.stdout.buffer
将数据重定向到stdout。我使用它,因为我还没有找到更好的方法将二进制数据从stdin传输到stdout。我将从sys.stdin.buffer.read(1024*100)
读取缓冲区的方式更改为sys.stdin.buffer.read(1)
,这很有帮助。看起来,sys.stdin.buffer.read
在获得所有字节数之前不会返回值。这是一个缓冲管道。总是。很高兴看到你找到了解决办法。如果你想有一个自定义的协议,你可以添加一个小的报头,它会告诉你下一个readhaving报头会带来多少数据,这是一个好主意,当我从这个POC移动到真正的程序时,我会记住它。非常感谢:)