C#读取重定向标准输入的难题

最近因为测试taskBus技术,需要在进程中重定向子进程(c#开发)的标准输入(stdin)。这样,C#子进程中直接可以Console.Read出主进程给的数据。

由于前期在C++、Python2/3、Node.JS等语言上均实现了子进程,而且非常简单,所以也就没当回事儿。没想到,CSharp实现起来却是困难重重!这里特此记录:

  • 如果主进程启动子进程后,没有向C#子进程的stdin写入任何东西,而是把stdin放在那里不管,则会导致子进程停在 Read()函数里一直等待。
  • 一旦进入上述等待状态,即使后续写入数据,也无法恢复。

这个问题超级诡异,我认为是.Net的BUG(4.6)。我在一个老外的博客里找到了几乎一样的遭遇:

https://daveaglick.com/posts/capturing-standard-input-in-csharp

最终借鉴Dave的代码,实现了读取字节的函数:

public byte[] read_from_stdin(int size)
{
    byte[] buffer = new byte[size];
    int red = 0;
    System.IO.Stream stream = Console.OpenStandardInput();
    int read = -1;
    AutoResetEvent gotInput = new AutoResetEvent(false);
    while (read< size)
    {
        Thread inputThread = new Thread(() =>
        {
            try
            {
                read = stream.Read(buffer, red, buffer.Length - red);
                red += read;
                gotInput.Set();
            }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
        })
        {
            IsBackground = true
        };
        inputThread.Start();
        // Timeout expired?
        if (!gotInput.WaitOne(100))
            inputThread.Abort();                    
    }
    return buffer;
}

主要的替代解决(很不优雅)是采用一个线程读取,一个线程监视,不管成不成功,100毫秒后都强制杀死读取线程。相关工程文件见

https://github.com/goldenhawking/taskBus/blob/master/module_templates/csharp/Program.cs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁劲犇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值