外部进程在异步读取输出时阻塞主线程

时间:2014-08-02 09:49:30

标签: c# wpf multithreading asynchronous

所以我的WPF应用程序中有以下代码

        ghci = new Process
        {
            StartInfo = new ProcessStartInfo("ghci")
            {
                WorkingDirectory = System.IO.Path.GetDirectoryName(path),
                Arguments = System.IO.Path.GetFileName(path),
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            }
        };
        ghci.OutputDataReceived += (obj, data) =>
        {
            this.Dispatcher.InvokeAsync(() =>
            {
                ghciOutput.AppendText(data.Data + "\n");
                ghciOutput.Focus();
                ghciOutput.CaretIndex = ghciOutput.Text.Length;
                ghciOutput.ScrollToEnd();
                ghciInput.Focus();
                Keyboard.Focus(ghciInput);
            });
        };
        ghci.Start();
        ghci.BeginOutputReadLine();

但是当进程开始输出大量数据时,对于该输出中的每一行,事件都会非常快速地触发,并且整个应用程序冻结。为什么会这样?我以为我已经确定它没有通过首先执行异步的BeginOutputReadLine(尽管我很可能不知道这意味着什么),然后在事件中做InvokeAsync以确保主线程在有时间时更新输出。

我还应该注意,当应用程序冻结时,输出文本框不会使用新数据进行更新,但这可能只是应用程序冻结的结果。

1 个答案:

答案 0 :(得分:2)

你需要缓冲tje OutputDataReceived缓冲区中的传入数据,然后通过InvokeAsync将其发送到UI(每2-3秒)左右,在任何情况下都比你更频繁地发送现在

您可以缓冲到string并且您可以每100行调度一次(为了不测量时间)。不要忘记在调度后清除字符串,或者只使用另一个实例并收集旧实例。

目前,您正在使用UI更新来杀死UI线程。

我认为这很清楚。如果你需要一个例子,请告诉我,我会看到我能做些什么。