Question

I'm running a windows form with a background worker to update a textbox based on the output of a python script. Its all working pretty well, except the redirected output is not in real time; its delayed pretty significantly.

Any ideas how I can increase the redirected outputs response time?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace JiraHeartBeat
{
    public partial class Form1 : Form
    {

        delegate void AppendTextDelegate(string text);
        BackgroundWorker Worker = new BackgroundWorker();

        public Form1()
        {
            InitializeComponent();

            Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
            Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);

        }

        void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            StartButton.PerformClick();
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            if (!Worker.IsBusy)
            {
                Worker.RunWorkerAsync();
            }
        }

        public void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Process pro = new Process();
            pro.StartInfo.RedirectStandardOutput = true;
            pro.StartInfo.RedirectStandardError = true;
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.CreateNoWindow = true;
            pro.EnableRaisingEvents = true;
            pro.OutputDataReceived += new DataReceivedEventHandler(OnDataReceived);
            pro.ErrorDataReceived += new DataReceivedEventHandler(OnDataReceived);

            pro.StartInfo.FileName = "C:\\Python27\\python.exe";
            pro.StartInfo.Arguments = "\"C:\\Python27\\myscript.py\"";

            try
            {
                pro.Start();
                pro.BeginOutputReadLine();
                pro.BeginErrorReadLine();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            Thread.Sleep(5000 * 60);
        }


        public void OnDataReceived(object sender, DataReceivedEventArgs e)
        {

            if (e.Data != null)
            {
                string temp = (e.Data) + Environment.NewLine;
                appendText(temp);

            }
        }
        public void appendText(string text)
        {
            if (ResultTextBox.InvokeRequired)
            {
                ResultTextBox.Invoke(new AppendTextDelegate(appendText), new object[] { text });
            }
            else
            {
                ResultTextBox.AppendText(text);
            }
        }
    }
}
Was it helpful?

Solution

Actually, the issue is that Python does not redirect output until the script is complete. I believe IronPython will redirect while the script is running (have not tested this though), but unfortunately, regular Python must wait for the script to end before redirecting output.

OTHER TIPS

Try removing the below line from the Worker_DoWork, I suspect it is delaying the execution of the RunWorkerCompleted event.

Thread.Sleep(5000 * 60);

EDIT

Since the above approach was attempted and did not solve the problem entirely I investigated a bit further and confirmed that when capturing the output from a python script the response is delayed. However, by adding a call to sys.stdout.flush() I was able to get the desired behavior. Here is the python script I used which worked successfully in my test.

import time
import sys

for x in xrange(0,11):
    print x
    time.sleep(1)
    sys.stdout.flush()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top