无法使用异步方法从C#app读取子进程的输出?

时间:2015-09-26 18:52:06

标签: c# asynchronous process stdout stdin

我正在尝试使用C#和Visual Studio 2013,Update 4在我的Windows 8.1机器上为EXE编写自己的交互式shell。代码运行时没有任何错误,但我从未在Read调用中看到任何回复从stdout读取的循环或读取stderr的循环。读取调用永远不会返回。我的方法出了什么问题?

我看到了这个相关的SO帖子,但我没有得到任何异常:

C# Read stdout of child process asynchronously

public partial class frmMain : Form
{
    private const string DIR_CHILDPROCESS = @"C:\Users\Robert\Documents\Visual Studio 2012\ChildProcess-5.3.1 - IDAvatars\";
    private const string EXE_NAME = @"childprocess.exe";

    Process _childProcess = null;

    public frmMain()
    {
        InitializeComponent();
    }

    private async Task ReadOutputFromChildProcess()
    {
        char[] aryC = new char[1];

        while (true)
        {
            // Get output from ChildProcess.
            int count = await this._childProcess.StandardOutput.ReadAsync(aryC, 0, 1);

            Debug.Write(aryC[0]);

            // await Task.Delay(50);
        }
    }

    private async Task ReadFromErrorsChildProcess()
    {
        char[] aryC = new char[1];

        while (true)
        {
            // Get output from ChildProcess.
            int count = await this._childProcess.StandardError.ReadAsync(aryC, 0, 1);

            Debug.Write(aryC[0]);

            // await Task.Delay(50);
        }
    }

    private void frmShell_Load(object sender, EventArgs e)
    {
        string target = Path.Combine(DIR_CHILDPROCESS, EXE_NAME);

        this._childProcess = new Process();

        this._childProcess.StartInfo.UseShellExecute = false;
        this._childProcess.StartInfo.RedirectStandardOutput = true;
        this._childProcess.StartInfo.RedirectStandardError = true;
        this._childProcess.StartInfo.RedirectStandardInput = true;
        this._childProcess.StartInfo.CreateNoWindow = true; 

        this._childProcess.EnableRaisingEvents = true;

        this._childProcess.StartInfo.FileName = target;

        this._childProcess.Exited += this._childProcess_Exited;

        // this._childProcess.StartInfo.Arguments = arguments;
        // this._childProcess.StartInfo.
        this._childProcess.StartInfo.WorkingDirectory = DIR_CHILDPROCESS;
        //this._childProcess.StartInfo.FileName = Path.Combine(DIR_CHILDPROCESS, EXE_NAME);
        //this._childProcess.StartInfo.UseShellExecute = false;
        //this._childProcess.StartInfo.RedirectStandardOutput = true;
        //this._childProcess.StartInfo.RedirectStandardError = true;
        //this._childProcess.StartInfo.RedirectStandardInput = true;
        //this._childProcess.StartInfo.CreateNoWindow = true;


        if (!this._childProcess.Start())
            MessageBox.Show("ChildProcess failed to start.", "Error");

        // Start the loop that reads output from ChildProcess.
        this.ReadOutputFromChildProcess();

        // Start the loop that reads error messages from ChildProcess.
        this.ReadFromErrorsChildProcess();

        Debug.WriteLine("ChildProcess launched successfully.");

        // this._childProcess.WaitForExit();

    }

    void _childProcess_Exited(object sender, EventArgs e)
    {
        Debug.WriteLine("Child process exited with exit code: " + this._childProcess.ExitCode.ToString());
    }

    private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
    {
        this._childProcess.Kill();
    }
}

1 个答案:

答案 0 :(得分:2)

  

我看到了这个相关的SO帖子,但我没有得到任何异常抛出   在所有

任何异步方法传播的任何异常都将被吞并到Task个对象中,您不会等待它们。如果要观察任何异常,可以同时执行两个异步操作,并使用Task.WhenAll等待它们:

private async void frmShell_Load(object sender, EventArgs e)
{
    var readOutputTask = this.ReadOutputFromChildProcess();
    var readErrorTask = this.ReadFromErrorsChildProcess();

    await Task.WhenAll(readOutputTask, readErrorTask);
}

否则,如果您希望两个操作按顺序执行,则可以单独await每个操作:

private async void frmShell_Load(object sender, EventArgs e)
{
    await ReadOutputFromChildProcess();
    await ReadFromErrorsChildProcess();
}