0

I'm creating a test program that reports back a command line tool's output to a text box in real time to understand how it works, and learn the groundwork for use in a future project. My current code simply pings the local loop back IP address five times and sends the output to a text box. Initially I had issues with the UI locking up during the 'ping', so I've incorporated a background worker so the UI remains responsive while the 'ping' command runs. However my issue is that I can't seem to get the ping output to display in the text box in real time (eg, so each of the 5 ping response appears in the text box as they would in a command prompt). Currently nothing happens for 5 seconds then the complete 'ping' results display in one go:

Before After

Here is my current code:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            bgw.WorkerReportsProgress = true;
            bgw.WorkerSupportsCancellation = true;
            bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
            bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        }

        //////////////////////////////////////////////////////////
        // Begin ping test
        //////////////////////////////////////////////////////////
        private void btnPing_Click(object sender, EventArgs e)
        {
            if (bgw.IsBusy != true)
            {
                bgw.RunWorkerAsync();
            }
        }

        //////////////////////////////////////////////////////////
        // Background worker
        //////////////////////////////////////////////////////////
        private void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            Process proc = new Process();
            proc.StartInfo.FileName = "ping";
            proc.StartInfo.Arguments = "127.0.0.1 -n 5";
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.CreateNoWindow = true;

            proc.Start();

            using (StreamReader reader = proc.StandardOutput)
            {
                string stdout = reader.ReadToEnd();
                this.Invoke((MethodInvoker)delegate
                {
                    txtOutput.AppendText(stdout);
                });
            }
            proc.WaitForExit();
        }

        //////////////////////////////////////////////////////////
        // Background worker completed
        //////////////////////////////////////////////////////////
        private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                btnPing.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                btnPing.Text = "Error: " + e.Error.Message;
            }
            else
            {
                btnPing.Text = "Success!";
            }
        }
    }

I have looked at similar posts and MSDN references but drawn blanks as either the techniques are beyond my current level of understanding, or seem to be unrelated. A pointer in the right direction would be appreciated.

Rawns
  • 865
  • 4
  • 27
  • The 5s "lag" is because you're using `reader.ReadToEnd()` but the `EndOfStream` will be passed to the `stdout` when process ends. – mrogal.ski Jan 27 '17 at 14:17
  • 1
    See https://stackoverflow.com/questions/415620/redirect-console-output-to-textbox-in-separate-program – sgmoore Jan 27 '17 at 14:19

0 Answers0