我在svn.exe周围写了一个快速而又脏的包装器来检索一些内容并用它做一些事情,但对于某些输入它偶尔会重复挂起并且无法完成.例如,一个调用是svn列表:
svn list "http://myserver:84/svn/Documents/Instruments/" --xml --no-auth-cache --username myuser --password mypassword
当我从命令shell执行此操作时,此命令行运行正常,但它在我的应用程序中挂起.运行它的我的c#代码是:
string cmd = "svn.exe"; string arguments = "list \"http://myserver:84/svn/Documents/Instruments/\" --xml --no-auth-cache --username myuser --password mypassword"; int ms = 5000; ProcessStartInfo psi = new ProcessStartInfo(cmd); psi.Arguments = arguments; psi.RedirectStandardOutput = true; psi.WindowStyle = ProcessWindowStyle.Normal; psi.UseShellExecute = false; Process proc = Process.Start(psi); StreamReader output = new StreamReader(proc.StandardOutput.BaseStream, Encoding.UTF8); proc.WaitForExit(ms); if (proc.HasExited) { return output.ReadToEnd(); }
这需要整整5000毫秒,永远不会完成.延长时间并没有帮助.在一个单独的命令提示符中,它立即运行,所以我很确定它与等待时间不足无关.但是,对于其他输入,这似乎工作正常.
我也尝试在这里运行一个单独的cmd.exe(其中exe是svn.exe,而args是原始的arg字符串),但仍然发生了挂起:
string cmd = "cmd"; string arguments = "/S /C \"" + exe + " " + args + "\"";
我可以搞砸了什么,我该如何调试这个外部流程?
编辑:
我现在正在解决这个问题.Mucho感谢Jon Skeet的建议,这确实很有效.我有另外一个关于我的处理方法的问题,因为我是一个多线程的新手.我想提出改善任何明显缺陷的建议或其他任何愚蠢的建议.我最终创建了一个包含stdout流的小类,一个用于保存输出的StringBuilder,以及一个告诉它何时完成的标志.然后我使用ThreadPool.QueueUserWorkItem并传入我的类的实例:
ProcessBufferHandler bufferHandler = new ProcessBufferHandler(proc.StandardOutput.BaseStream, Encoding.UTF8); ThreadPool.QueueUserWorkItem(ProcessStream, bufferHandler); proc.WaitForExit(ms); if (proc.HasExited) { bufferHandler.Stop(); return bufferHandler.ReadToEnd(); }
......而且......
private class ProcessBufferHandler { public Stream stream; public StringBuilder sb; public Encoding encoding; public State state; public enum State { Running, Stopped } public ProcessBufferHandler(Stream stream, Encoding encoding) { this.stream = stream; this.sb = new StringBuilder(); this.encoding = encoding; state = State.Running; } public void ProcessBuffer() { sb.Append(new StreamReader(stream, encoding).ReadToEnd()); } public string ReadToEnd() { return sb.ToString(); } public void Stop() { state = State.Stopped; } }
这似乎有效,但我怀疑这是最好的方法.这合理吗?我该怎么做才能改善它?
一个标准问题:该过程可能正在等待您阅读其输出.在等待它退出时,创建一个单独的线程来读取其标准输出.这有点痛苦,但这可能是问题所在.
Jon Skeet是对的钱!
如果您在启动svn命令后不介意轮询,请尝试以下操作:
Process command = new Process(); command.EnableRaisingEvents = false; command.StartInfo.FileName = "svn.exe"; command.StartInfo.Arguments = "your svn arguments here"; command.StartInfo.UseShellExecute = false; command.StartInfo.RedirectStandardOutput = true; command.Start(); while (!command.StandardOutput.EndOfStream) { Console.WriteLine(command.StandardOutput.ReadLine()); }