簡體   English   中英

使用批處理文件執行的輸出實時更新C#表單RichTextBox內容,而無需等待批處理命令執行完成

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

下面是表格中的C#代碼。

    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)));
    }

我將Windows批處理文件傳遞給callInfraComamnd ,它的代碼塊運行正常。 但是,我的批處理文件需要花費5分鍾以上的時間才能完成,在此期間,我的表單處於凍結狀態,並且批處理過程完成后,它將以塊的形式顯示該批處理文件的所有輸出。

理想情況下,我希望在后台運行批處理時在TextBox查看進度(批處理文件的中間輸出)。

誰能建議我如何解決它(我正在使用.NET 4)?

您需要在Task執行private void callInfraCommand(string cmd)的內容。 m_command.WaitForExit()阻止調用此函數的線程(UI線程)。 因為它阻止它不能處理的編組代碼proc_DataReceived()之前m_command.WaitForExit()完成。

選項1:不要等待退出會阻塞UI線程的退出private void callInfraCommand(string cmd){// ...

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

選項2:在單獨的任務中調用阻止部分

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()!
            }
    );
}

更新:選項3:在完成其他步驟中定義的過程之后,執行一些操作。

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

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


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

                afterFinishedAction();
            }
    );
}

@Sam然后,我建議您創建一個任務,其中包含每個過程調用的循環並離開waitForExit。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM