C# ProcessStartInfo 读取输出 "live"(并发)

标签 c# wpf multithreading process

我正在尝试编写一个控制台包装器 WPF gui,它只运行一系列 .bat 文件,我希望能够“实时”查看 .bat 文件的任何输出(就像它在命令)。

我研究了 OutputDataReceived 和事件处理程序,它们附加文本然后将其发送到屏幕,但它仍然会等到进程完成后屏幕上才会显示任何内容。

如何让 .bat 的输出“实时”出现?


到目前为止我的代码片段(这是一种形式):

表单有一个按钮(go)和一个多行文本字段(textArea)。

private void go_Click(object sender, EventArgs e)
{
    ExecuteCommand();
}

public void ExecuteCommand()
{

    int ExitCode;
    ProcessStartInfo ProcessInfo;
    Process Process;

    //ProcessInfo = new ProcessStartInfo("cmd.exe", "/C z:\foo.bat");
    ProcessInfo = new ProcessStartInfo(@"z:\foo.bat"); ;

    ProcessInfo.CreateNoWindow = true;
    ProcessInfo.UseShellExecute = false;

    ProcessInfo.RedirectStandardError = true;
    ProcessInfo.RedirectStandardOutput = true;

    Process = new Process();
    Process.StartInfo = ProcessInfo;

    Process.OutputDataReceived += new DataReceivedEventHandler(OutputToTextArea);

    Process.Start();

    // Start the asynchronous read of the sort output stream.
    Process.BeginOutputReadLine();

    Process.WaitForExit();

    ExitCode = Process.ExitCode;
    Process.Close();
}

private int numOutputLines = 0;
private void OutputToTextArea(object sendingProcess, DataReceivedEventArgs outLine)
{
    // Collect the sort command output. 
    if (!String.IsNullOrEmpty(outLine.Data))
    {
        numOutputLines++;

        this.AppendToTextArea("[" + numOutputLines.ToString() + "] - " + outLine.Data + Environment.NewLine);
    }
}

private void AppendToTextArea(string s)
{
    if (this.textArea.InvokeRequired)
    {
        // It's on a different thread, so use Invoke.
        this.BeginInvoke (new MethodInvoker(() => textArea.AppendText(s)));
    } else {
        textArea.AppendText(s);
    }
}

我的 foo.bat 只是一个 for 循环:

ECHO OFF

FOR /L %%i IN (1,1,10) DO (
   echo %%i
   ping -n 2 127.0.0.1 >nul
)

最佳答案

是的,您当前正在阻塞主线程(即 UI 线程),因为您在 ExecuteCommand 中等待进程退出,这是直接从 UI 线程调用的(在 go_Click).

只需启动一个新线程(或使用ThreadPool)(Winforms 示例):

private void button1_Click(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(this.ExecuteCommand));
}

public void ExecuteCommand(object state)
{
    ...
}

如果您使用的是 WPF,您可能希望使用 BackgroundWorker .

关于C# ProcessStartInfo 读取输出 "live"(并发),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14582794/

相关文章:

c# - 为什么 CUDA 内核中的 z 总是零

c# - 如何操作gridview的各个组标题

c# - 按钮 url 缓存 Dynamics CRM 4 问题

c# - Livecharts Geared 在缩放到特定位置时抛出未处理的 ArgumentOutOfRangeException

wpf - 可观察的集合可以作为ref参数传递吗?

asp.net - 每个请求 asp.net 单线程

c# - linq to entities 无法将 int 转换为字符串

wpf - MVVM-Light/WPF 导航应用

C++线程创建大开销

java - ExecutorService 池中的数组中所有元素的总和不起作用