输入数据错误不足时,StdIn管道不会刷新?

时间:2019-04-03 13:20:19

标签: c# linux .net-core

我正在研究启动一个进程,然后写入该进程的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, 

其中pProcess类的实例

编辑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的建议

0 个答案:

没有答案