首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >pConsole.StartInfo.RedirectStandardOutput和pConsole.Exited事件(c#)

pConsole.StartInfo.RedirectStandardOutput和pConsole.Exited事件(c#)
EN

Stack Overflow用户
提问于 2008-11-03 11:02:28
回答 4查看 2.4K关注 0票数 3

我有一个GUI应用程序,它(在一个新进程中)执行“控制台”应用程序并解析输出。为了重定向输出,我将pConsole.StartInfo.RedirectStandardOutput设置为true。我还订阅了event pConsole.Exited。

我看到的问题是,我必须在退出的事件处理程序中使用Thread.Sleep()来获取最后的数据。

我的退出事件处理程序如下所示:

代码语言:javascript
运行
复制
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;

退出的事件似乎在我的最后一个pConsole_DataAvailableEvent之前执行。有人知道这是怎么发生的吗?

在开始执行下一个控制台应用程序之前,我还使用了互斥锁/锁来确保退出的事件已经完成。

EN

回答 4

Stack Overflow用户

发布于 2008-11-03 18:06:58

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

1)删除已退出的事件处理程序,改为检查OutputDataReceived处理程序中的Process.HasExited。

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

票数 3
EN

Stack Overflow用户

发布于 2008-11-03 11:31:57

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

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

代码语言:javascript
运行
复制
            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);
         };
    }
票数 2
EN

Stack Overflow用户

发布于 2008-11-03 11:09:45

我强烈怀疑这只是操作系统刷新所有输出缓冲区。看起来你的解决办法还可以,尽管它显然很丑陋(不是你的错),而且在某些情况下睡眠时间可能会过长,而在某些病态的其他情况下睡眠时间可能不够长。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/258339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档