简体   繁体   中英

Update C# form RichTextBox content (in realtime) with the output of the batch file execution without waiting for the batch command execution to finish

Below is my C# code in the form.

    private void callInfraCommand(string cmd)
    {
        string os_name = GetOSFriendlyName();
        var m_command = new System.Diagnostics.Process();

        // set up output redirection
        m_command.StartInfo.RedirectStandardOutput = true;
        m_command.StartInfo.RedirectStandardError = true;
        m_command.StartInfo.CreateNoWindow = true;
        m_command.StartInfo.UseShellExecute = false;
        m_command.StartInfo.CreateNoWindow = true;
        m_command.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        m_command.EnableRaisingEvents = true;

        // see below for output handler
        m_command.ErrorDataReceived += proc_DataReceived;
        m_command.OutputDataReceived += proc_DataReceived;

        if (os_name.Contains("Windows 7") || os_name.Contains("2008") || os_name.Contains("Windows 8") || os_name.Contains("2012"))
            m_command.StartInfo.FileName = @"C:\windows\system32\cmd.exe";
        else
            m_command.StartInfo.FileName = @"C:\WINNT\system32\cmd.exe";

        m_command.StartInfo.Arguments = cmd;
        m_command.Start();

        m_command.BeginErrorReadLine();
        m_command.BeginOutputReadLine();
        m_command.WaitForExit();
    }

    private void proc_DataReceived(object sender, DataReceivedEventArgs e)
    {
        // output will be in string e.Data
        if (e.Data != null)
            this.BeginInvoke(new Action(() => deploy_result_txt.Text += (Environment.NewLine + e.Data)));
    }

I am passing the windows batch file to callInfraComamnd and it's block of code is working fine. But, my batch file is taking more than 5 minutes to finish and during that time, my form is freezing and after the batch process completes it displaying all the output of the batch file in chunk.

Ideally, i would like to see the progress (intermediate output of the batch file) in the TextBox while the batch process is running in the background.

Can anyone please advise how can I resolve it (i am using .NET 4) ?

You need to execute the content of private void callInfraCommand(string cmd) in a Task . The m_command.WaitForExit() blocks the thread calling this function (the UI thread). Since it's blocked it cannot process the marshalled code in proc_DataReceived() before m_command.WaitForExit() finished.

Option 1: don't wait for exit which would block the UI thread private void callInfraCommand(string cmd) { //...

    m_command.BeginErrorReadLine();
    m_command.BeginOutputReadLine();
    // m_command.WaitForExit();
}

Option 2: Call the blocking part in a separate task

private void callInfraCommand(string cmd)
{
    //...

    m_command.BeginErrorReadLine();
    m_command.BeginOutputReadLine();


    Task.Factory.StartNew(
        () => 
            {
                m_command.WaitForExit()
                // code to clean up etc.
                // if there is nothing in here, there's no need to call WaitForExit()!
            }
    );
}

UPDATE: Option 3: Do something after the process finished which is defined elsewhere.

private void callInfraCommand(string cmd, Action afterFinishedAction)
{
    //...

    m_command.BeginErrorReadLine();
    m_command.BeginOutputReadLine();


    Task.Factory.StartNew(
        () => 
            {
                m_command.WaitForExit()

                afterFinishedAction();
            }
    );
}

@Sam然后,我建议您创建一个任务,其中包含每个过程调用的循环并离开waitForExit。

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