简体   繁体   中英

Getting line by line output from a started process

I'm trying to retrieve the output lines generated by a process I started, here's the code

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (myData singleJob in e.Argument as List<myData>)
    {
        ProcessStartInfo psi = new ProcessStartInfo("myCommandLineProgram.exe");
        psi.Arguments = "\"" + singleJob.row + "\"";
        psi.CreateNoWindow = true;
        psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;
        psi.UseShellExecute = false;
        Process p = new Process();
        p.StartInfo = psi;
        p.Start();
        StreamReader sr = p.StandardOutput ;
        string line;
        while ((line = sr.ReadLine()) != null )
        {
            this.Invoke((MethodInvoker)delegate
            {
                    richTextBox1.AppendText(sr.ReadLine() + Environment.NewLine);
                    richTextBox1.ScrollToCaret();   

            });
        }

        //StreamReader streamOutput = p.StandardOutput;
        //string content = streamOutput.ReadToEnd();   
        //this.Invoke((MethodInvoker)delegate
        //{
        //    richTextBox1.AppendText(content + Environment.NewLine);
        //});

        p.WaitForExit();
    }
}

While the commented out code is always working (but it doesn't parse line by line), the code above is somehow faulty, indeed some lines fail to appear into the richtextbox and some others are blank.

Thanks

Shouldn't that be something like

richTextBox1.AppendText(line + Environment.NewLine);

( line instead of sr.ReadLine() )?

Calling readLine() twice will discard every second line.

Also, since you're calling ReadLine in the delegate you cannot control when the read occurs. It might be that there were several ReadLines() (from the while line) in between.

Note, that you should also NOT use the line variable: This variable always references the same line variable in the loop, this one might contain new content at the time the AppendText is executed. You should introduce a new local variable inside the loop like

 while ((line = sr.ReadLine()) != null )
 {
   var theLine = line;
   this.Invoke((MethodInvoker)delegate
   {
       richTextBox1.AppendText(theLine + Environment.NewLine);
       richTextBox1.ScrollToCaret();   
   });
 }

Just change here instead of ReadLine() , put line . You have already read the line in your while loop

string appendingLine = line;
this.Invoke((MethodInvoker)delegate
{
          richTextBox1.AppendText(appendingLine + Environment.NewLine);
          richTextBox1.ScrollToCaret();   

});

EDIT: The answer MartinStettner gave is better one. There may be the case where line changes before the delegate is executed, therefore some lines can be lost while others can be repeated. Therefore I will change my answer according to Martin's and I want to point out that he should be the one who will take the credit for this answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM