zoukankan      html  css  js  c++  java
  • Process.StandardOutput使用注意事项 Anny

    前段时间,经常使用C#调用控制台程序,便写了一个通用的方法,起初可以正常工作,直到遇到控制台程序输出内容较多时,发现控制台程序无法自动终止(任务管理器中始终有这个控制台进程,cpu使用率0),查阅msdn,才知道原来出现了死锁现象。

    下面是最初的代码:

       /// <summary>
            /// common method to execute tool
            /// </summary>
            /// <param name="toolFile">tool's path</param>
            /// <param name="args">arguments</param>
            private static void ExecuteTool(string toolFile, string args)
            {
                Process p;
                ProcessStartInfo psi;
                psi = new ProcessStartInfo(toolFile);
                psi.Arguments += args;

                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;  //允许重定向标准输出
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.WindowStyle = ProcessWindowStyle.Hidden;

                p = Process.Start(psi);

                p.WaitForExit();
                p.Close();
            }

    在读取StandardOutput流时,有两种方式,即同步和异步。

    同步方式,会在读取流的一方和写入流的一方形成依赖关系,这种依赖关系形成了死锁的条件。当要写或读足够多的数据时,双方会等待对方写完或者读完,彼此的等待导致了死锁的产生。具体的解释可以参见msdn:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=VS.80).aspx

    如果我们不需要重定向输出,可以将psi.RedirectStandardOutput设置为false。

    如果需要重定向输出,那么必须解决潜在的死锁问题,方法有两个:

    方法一:Call ReadToEnd() before WaitForExit()

    private static void ExecuteTool(string toolFile, string args)
            {
                Process p;
                ProcessStartInfo psi;
                psi = new ProcessStartInfo(toolFile);
                psi.Arguments += args;

                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;  //允许重定向标准输出
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.WindowStyle = ProcessWindowStyle.Hidden;

                p = Process.Start(psi);

        string output = p.StandardOutput.ReadToEnd(); //Call ReadToEnd() before WaitForExit()

                p.WaitForExit();
                p.Close();
            }

    方法二:采用异步方式(适用于同时获取标准输出流和错误流)

    private static void ExecuteTool(string toolFile, string args)
            {
                Process p;
                ProcessStartInfo psi;
                psi = new ProcessStartInfo(toolFile);
                psi.Arguments += args;

                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;  //允许重定向标准输出

        psi.RedirectStandardError = true;
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.WindowStyle = ProcessWindowStyle.Hidden;

                p = Process.Start(psi);

        p.OutputDataReceived += new DataReceivedEventHandler(OnDataReceived);
                p.BeginOutputReadLine();

                p.WaitForExit();

        if (p.ExitCode != 0)
                {
                    result.Append(p.StandardError.ReadToEnd());
                }           
                p.Close();
            }

      private static void OnDataReceived(object Sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                {
                    result.Append(e.Data);
                }
            }

  • 相关阅读:
    Selenium 中ExpectedConditions 用法说明(最全整理)
    logback的使用和logback.xml详解
    彻底征服 Spring AOP 之 实战篇
    彻底征服 Spring AOP 之 理论篇
    面试
    Java面试
    Python的数据类型与数据结构
    利用Python的 counter内置函数,统计文本中的单词数量
    python爬虫Urllib实战
    python爬虫实战一(基于正则表达式学习)
  • 原文地址:https://www.cnblogs.com/limei/p/1743707.html
Copyright © 2011-2022 走看看