3

I have a GUI application that executes (in a new process) "console" applications and parse the output. To redirect the Output i set the pConsole.StartInfo.RedirectStandardOutput to true. I also subscribes to the event pConsole.Exited.

The problem I see is that I have to use Thread.Sleep() in the Exited event handler to get the last data.

My Exited event handler looks like this:

Thread.Sleep(100); // Wait for additional data (if any).
pConsole.OutputDataReceived -= new System.Diagnostics.DataReceivedEventHandler(this.localTerminal_DataAvailableEvent);
int exit = pConsole.ExitCode;
pConsole.Dispose();
pConsole = null;

It seems that the Exited event executes before my last pConsole_DataAvailableEvent. Anyone knows how/why this is happening?

I also use a mutex/lock to make sure my Exited event is finished before I start execute my next console application.

4

4 回答 4

3

问题几乎可以肯定是输出缓冲:进程退出,触发您的 Exited 事件,但一些输出数据仍在缓冲区中。您的 hack 在某些情况下可能会奏效,但其他方法可能更强大。考虑:

1) 消除 Exited 事件处理程序,而是在 OutputDataReceived 处理程序中检查 Process.HasExited。

2) 不要使用 OutputDataReceived 处理程序,而只需在 Process.StandardOutput 流上调用 Read()。流关闭后进行后处理清理。

于 2008-11-03T18:06:58.157 回答
2

我不知道它是否更好,但我一直在寻找类似的东西,使用线程来读取 stderr/stdout,如下所示。它涉及一些额外的线程(以避免死锁/复杂的异步代码),但似乎工作得相当稳健。

这里的关键是我Join()在处理 IO 的两个线程上,所以我只有在两个输出流都被完全消耗后才继续。

            using (Process proc = Process.Start(psi))
            {
                Thread stdErr = new Thread(DumpStream(proc.StandardError, Console.Error));
                Thread stdOut = new Thread(DumpStream(proc.StandardOutput, Console.Out));
                stdErr.Name = "stderr reader";
                stdOut.Name = "stdout reader";
                stdErr.Start();
                stdOut.Start();
                proc.WaitForExit();
                stdOut.Join();
                stdErr.Join();
                if (proc.ExitCode != 0) {...} // etc
            }

    static ThreadStart DumpStream(TextReader reader, TextWriter writer)
    {
        return (ThreadStart) delegate
         {
             string line;
             while ((line = reader.ReadLine()) != null) writer.WriteLine(line);
         };
    }
于 2008-11-03T11:31:57.190 回答
1

I strongly suspect that it's just the operating system flushing any output buffers. It looks like your workaround is okay-ish, although obviously it's ugly (not your fault) and the length of sleep could be wastefully long in some cases and not long enough in some pathological other cases.

于 2008-11-03T11:09:44.957 回答
0

除了 Marc Gravell 的回答

proc.StandardError、proc.StandardOutput 都有一个 EndOfStream 方法。这对于确定在用户输入/提示之前输出不产生换行符的情况很有用

于 2011-01-04T09:27:53.670 回答