c#中的事件驱动stdin

本文关键字:stdin 事件驱动 | 更新日期: 2023-09-27 18:03:37

c#是否为我自己的进程提供在stdin流上接收数据时的事件?比如过程。OutputDataReceived,我只需要InputDataReceived的事件。

我已经搜索了高和低,并学会了重定向stdin->stdout,监控衍生应用程序的输出流和大量其他东西,但没有人显示收到stdin时触发哪个事件。除非我在main()中使用哑轮询循环。

// dumb polling loop -- is this the only way? does this consume a lot of CPU?
while ((line = Console.ReadLine()) != null && line != "") {
     // do work
}

另外,我需要从流中获取二进制数据,像这样:

using (Stream stdin = Console.OpenStandardInput())
using (Stream stdout = Console.OpenStandardOutput())
{
    byte[] buffer = new byte[2048];
    int bytes;
    while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0) {
        stdout.Write(buffer, 0, bytes);
    }
}

c#中的事件驱动stdin

轮询循环不会消耗太多CPU,因为ReadLine阻塞并等待。将此代码放入自己的工作线程中,并从中引发事件。据我所知,. net中没有这样的特性。

编辑:我一开始就错了。纠正:

你实际上可以从stdin中读取二进制数据,正如这个SO答案所说:

要读取二进制,最好的方法是使用原始输入流——这里在stdin和stdout之间显示类似"echo"的东西:

using (Stream stdin = Console.OpenStandardInput())
using (Stream stdout = Console.OpenStandardOutput())
{
    byte[] buffer = new byte[2048];
    int bytes;
    while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0) {
        stdout.Write(buffer, 0, bytes);
    }
}

这是一个异步方法。与OutputDataReceived一样,回调在换行符上运行。对于二进制,流式传输到base64可能有效。转换成二进制流比较困难,因为你不能只检查换行符

using System.Diagnostics;
using System.Threading.Tasks;
public static void ListenToParent(Action<string> onMessageFromParent)
{
    Task.Run(async () =>
    {
        while (true) // Loop runs only once per line received
        {
            var text = await Console.In.ReadLineAsync();
            onMessageFromParent(text);
        }
    });
}
下面是我的父应用程序如何设置子进程:
var child = new Process()
{
    EnableRaisingEvents = true,
    StartInfo =
    {
        FileName = ..., // .exe path
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        UseShellExecute = false,
        CreateNoWindow = true
    },
};
child.Start();
child.BeginOutputReadLine();

…以及它如何向子进程发送一行:

child.StandardInput.WriteLine("Message from parent");