C#异步从重定向的标准输出读取数据



我正在开发一个C#wfa,让我可以使用化学软件做一些事情:gamess。

基本上,我有一个批处理文件,当使用适当的参数返回文件时,该文件带有原子分析所需的数据。

在我的应用程序表单中,我设置了一个只读文本框,其中包含该过程的输出。我通过重定向标准输出来完成此操作。此读取是以同步的方式完成的。对于小输出来说,效果很好,但很多时候的线路驱逐了240k。我的过程在结束时会自动关闭(最后指令是"退出",而不是"退出/b"(。

正如您(可能(确定的那样,主表单变得不稳定,并且在过程结束之前不允许任何用户输入。这是一个问题...

我已经尝试了对我代码中不同功能的文件流读取的异步,并且效果很好,但是我对涉及标准输出的内容感到困惑。我无法找到正确的方法。

到目前为止,我的代码:

private void Button1_Click(object sender, EventArgs e)
{
            if (!String.IsNullOrEmpty(Input_job_file) && !String.IsNullOrEmpty(Log_file))
            {
                textBox3.Text = "Executing code...rn";
                string outtext;
                string batpath = string.Format(Settings.Default.path_to_gamess + "\rungms.bat");
                string arguments = string.Format("{0} {1} {2} 0 {3}", Input_job_file, Settings.Default.version, Ncpus, Log_file);
                //Here we need to copy the input file to the gamess directory in order to avoid errors
                File.Copy(Input_job_file, Settings.Default.path_to_gamess + "\" + FileNameWithoutExtension + ".inp");
                Process gamessjob = new Process();
                gamessjob.StartInfo.ErrorDialog = true;
                gamessjob.StartInfo.UseShellExecute = false;
                gamessjob.StartInfo.CreateNoWindow = true;
                gamessjob.StartInfo.RedirectStandardOutput = true;
                gamessjob.StartInfo.RedirectStandardError = true;
                gamessjob.EnableRaisingEvents = true;
                gamessjob.StartInfo.WorkingDirectory = Settings.Default.path_to_gamess;
                gamessjob.StartInfo.FileName = batpath;
                gamessjob.StartInfo.Arguments = arguments; //input_file, version, number_of_processors, "0", output_name]
                gamessjob.Start();
            //STDOUT redirection to our textbox in readonly mode
            outtext = gamessjob.StandardOutput.ReadToEnd();
            textBox3.Text += outtext + "rnProcess executed!";
            //here we clean up some stuff after GAMESS code ends
            File.Delete(Settings.Default.path_to_gamess + "\" + FileNameWithoutExtension + ".inp");
            MessageBox.Show("Code executed!nCheck output for errors or messages.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        else MessageBox.Show("Input file and/or output location is invalid!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
//ASYNC
byte[] result;
textBox6.Text = "Executing code...rnn";
using (FileStream SourceStream = File.Open(Input_dat_file, FileMode.Open))
{
        result = new byte[SourceStream.Length];
        await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
}

理想情况下,读取异步中重定向的标准输出应该解决我的应用程序的僵局(对吗?(,或者至少减少其持续时间。也许如果我使用ReadLineAsync((而不是ReadToendAsync((进行此操作,则文本框将更频繁地更新,因此,看到更"令人愉快"。

我已经搜索了辅助操作教程,但所有这些操作都显示了基于文件的操作。寻求Microsoft参考的重定向标准输出和异步使我更加困惑。

有人可以帮助我找出一种通过ReadlineAsync((?

读取输出线的方法

得到了它。这里遵循有效的代码。这样,文本框将按线路更新,而deadBlock不再发生。

public async void Button1_Click(object sender, EventArgs e)
    {
        if (!String.IsNullOrEmpty(Input_job_file) && !String.IsNullOrEmpty(Log_file ))
        {
            textBox3.Text = "Executing code...rn";
            string outtext;
            string batpath = string.Format(Settings.Default.path_to_gamess + "\rungms.bat");
            string arguments = string.Format("{0} {1} {2} 0 {3}", Input_job_file, Settings.Default.version, Ncpus, Log_file);
            //Here we need to copy the input file to the gamess directory in order to avoid errors
            File.Copy(Input_job_file, Settings.Default.path_to_gamess + "\" + FileNameWithoutExtension + ".inp");
            Process gamessjob = new Process();
            gamessjob.StartInfo.ErrorDialog = true;
            gamessjob.StartInfo.UseShellExecute = false;
            gamessjob.StartInfo.CreateNoWindow = true;
            gamessjob.StartInfo.RedirectStandardOutput = true;
            gamessjob.StartInfo.RedirectStandardError = true;
            gamessjob.EnableRaisingEvents = true;
            gamessjob.StartInfo.WorkingDirectory = Settings.Default.path_to_gamess;
            gamessjob.StartInfo.FileName = batpath;
            gamessjob.StartInfo.Arguments = arguments; //input_file, version, number_of_processors, "0", output_name]
            gamessjob.Start();
            //STDOUT redirection to our textbox in readonly mode
            while((outtext = await gamessjob.StandardOutput.ReadLineAsync()) != null)
            {
                textBox3.Text += outtext + "rn";
            }
            textBox3.Text += "rnProcess executed!";
            //here we clean up some stuff after GAMESS code ends
            File.Delete(Settings.Default.path_to_gamess + "\" + FileNameWithoutExtension + ".inp");
            MessageBox.Show("Code executed!nCheck output for errors or messages.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        else MessageBox.Show("Input file and/or output location is invalid!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }

最新更新