C#等待重定向的所有日期

时间:2015-12-14 11:29:07

标签: c# io-redirection

我将输出从我的进程(proc)重定向到richtextbox(richTextBoxOutput)。在重定向之前,它会写入richtextbox语句" BEFORE OUTPUT DATA"。然后它应该写出来自进程的所有数据,写入后写句子"输出数据后#34;。但是,最后这句话永远不会到最后。它始终位于richtextbox中间重定向日期之间的某个位置。你能帮我解决一下吗?

richTextBoxOutput.AppendText("BEFORE OUTPUT DATA");
Process proc = new Process();
proc.StartInfo.FileName = command;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.OutputDataReceived += new DataReceivedEventHandler
(
            (s, e) =>
            {
                if (richTextBoxOutput.InvokeRequired)
                {
                    richTextBoxOutput.Invoke(new Action(() => richTextBoxOutput.AppendText(e.Data + "\n")));
                }
                else
                    richTextBoxOutput.AppendText(e.Data + "\n");
            }
);
proc.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { richTextBoxOutput.AppendText(e.Data + "\n"); });
proc.Start();
proc.BeginOutputReadLine();
while (!proc.HasExited)
{
        Application.DoEvents(); //Instead of proc.WaitForExit()             
}
richTextBoxOutput.AppendText("AFTER OUTPUT DATA");

2 个答案:

答案 0 :(得分:1)

我可以建议采用异步方法解决问题吗? 是的,您将不得不处理跨线程调用,因为您正在从另一个线程写入窗体(类似文本框)组件,但好的部分是您可以使用proc.WaitForExit而无需担心冻结界面(没有这个令人讨厌的循环非常无效,因为它会让你的应用程序烧坏CPU)并且有一个ContinueWith子句来追加你的"输出后的数据"!

答案 1 :(得分:1)

最小工作样本:

    private void btnRun_Click(object sender, EventArgs e) {
        Task.Factory.StartNew(this.StdOutWorker);
    }

    private void StdOutWorker() {
        this.AppendLine("BEFORE OUTPUT DATA");

        // "CmdRandomGenerator.exe" will print random numbers to standard output in infinity loop
        ProcessStartInfo pi = new ProcessStartInfo("CmdRandomGenerator.exe") {
            RedirectStandardOutput = true,
            UseShellExecute = false
        };
        var proc = new Process{
            StartInfo = pi,
            EnableRaisingEvents = true
        };
        proc.Start();

        while (!proc.HasExited) {
            var line = proc.StandardOutput.ReadLine();
            this.AppendLine(line);
        }

        this.AppendLine("AFTER OUTPUT DATA");
    }

    private void AppendLine(string line) {
        Action act = () => {
            this.rtbOutput.AppendText(line + Environment.NewLine);
        };

        // UI objects must be accessed in UI thread
        this.BeginInvoke(act);
    }

这个想法是,进程的读取是在后台线程中,并且值不会等待结果传递给UI线程(火和忘记)。

从理论上讲,观察过程中的值可能比UI可以处理的速度快。在这种情况下,你必须扔掉一些值(采样)。 但是我尝试使用while(true) { Console.WriteLine(random()); }并且UI速度较慢但仍然响应。