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);
                }
            }

  • 相关阅读:
    vue+element的el-menu组件实现路由跳转及当前项的设置
    继承与多态
    八、使用for解决简单的问题
    六、Js数组的使用方法
    五、JS操作HTML方法
    四、初步入门JS的用法
    三、html总结
    二、表格<table>的使用
    一、初步接触html,基本标签和ul、ol的用法
    运算符的分类
  • 原文地址:https://www.cnblogs.com/limei/p/1743707.html
Copyright © 2011-2022 走看看