解决Process因缓冲区满而导至进程阻塞的办法

首先我们看一下出现缓冲区写满的做法:

折叠C# 代码
  1. Process p = CreateProcess("cmd",dir);//假如此处为我们从工厂中实例化一个调用cmd命令的进程   
  2. p.Start();   
  3. //从这里执行一个批处理或控制台程序,也可以是一堆CMD下的命令,我们通常会用这些来做大量的文件拷贝等操作   
  4. p.StandardInput.WriteLine("\"" + filename + "\" " + args);//写入执行参数   
  5. p.StandardInput.WriteLine("exit");//输入退出   
  6. //从此处获取所有输出信息   
  7. string result = p.StandardOutput.ReadToEnd();   
  8. p.WaitForExit();   
  9. //退出  

上面的做法本身没有什么问题,但有二个缺点。

1,如果执行的程序有大量的输出信息,会导致进程阻塞,程序至此不会再跑。

2,如果我要同步获取输出信息也不可能,只能等所有的执行完成才行。

 

下面我们来解决这个问题:

首先定义一个工厂用来生成进程:

折叠C# 代码
  1.         /// <summary>   
  2.         /// 生成进程   
  3.         /// </summary>   
  4.         /// <param name="filename"></param>   
  5.         /// <returns></returns>   
  6.         public static Process CreateProcess(string filename, string dir)   
  7.         {   
  8.   
  9.             Process p = new Process();//进程   
  10.             p.StartInfo.FileName = filename;   
  11.             p.StartInfo.RedirectStandardOutput = true;   
  12.             p.StartInfo.UseShellExecute = false;   
  13.             p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;   
  14.             p.StartInfo.CreateNoWindow = true;   
  15.            //下面二句不可少,不然会出错   
  16.             p.StartInfo.RedirectStandardInput = true;               
  17.             p.StartInfo.RedirectStandardError = true;   
  18.             if (!string.IsNullOrEmpty(dir))   
  19.                 p.StartInfo.WorkingDirectory = dir;   
  20.   
  21.             return p;   
  22.   
  23.         }   

然后我们调用它生成一个进程:

折叠C# 代码
  1. Process p = CreateProcess(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),"cmd.exe"), dir);   
  2.                 StringBuilder result = new StringBuilder();   
  3.   
  4. //这里就是我们用来异步读取输出的二个委托事件   
  5. //一个是正确的信息,另一个是错误的信息输出   
  6. p.ErrorDataReceived += new DataReceivedEventHandler(delegate(object sender, DataReceivedEventArgs e)   
  7.                 {   
  8.                     //也可以是你自义定的其它处理,比如用console.write打印出来等。ShowErrorInfo(e.Data);   
  9.                     result.AppendLine(e.Data);   //收集所有的出错信息                    
  10.                 });   
  11.                 p.OutputDataReceived += new DataReceivedEventHandler(delegate(object sender, DataReceivedEventArgs e)   
  12.                 {   
  13.                     ShowNormalInfo(e.Data);   
  14.                     result.AppendLine(e.Data);                      
  15.                 });   
  16. p.Start();   
  17.   
  18. //这二句别忘了,不然不会触发上面的事件   
  19. p.BeginErrorReadLine();   
  20. p.BeginOutputReadLine();   
  21.   
  22. //可以做你要的操作,执行批处理或其它控制台程序   
  23. //。。。。。。。。。。。   
  24.   
  25. //p.StandardInput.WriteLine(input);   
  26. ///////////////   
  27.   
  28. p.StandardInput.WriteLine("exit");//最后打入退出命令   
  29.   
  30. p.WaitForExit();   
  31. p.Close();   
  32. p.Dispose();  

这样就不怕太多的输出信息阻塞进程了,希望大家有用!

posted @ 2011-09-23 19:53  Areas  阅读(635)  评论(0编辑  收藏  举报