Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hanging process when run with .NET Process.Start -- what's wrong?

I wrote a quick and dirty wrapper around svn.exe to retrieve some content and do something with it, but for certain inputs it occasionally and reproducibly hangs and won't finish. For example, one call is to svn list:

svn list "http://myserver:84/svn/Documents/Instruments/" --xml  --no-auth-cache --username myuser --password mypassword 

This command line runs fine when I just do it from a command shell, but it hangs in my app. My c# code to run this is:

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

This takes the full 5000 ms and never finishes. Extending the time doesn't help. In a separate command prompt, it runs instantly, so I'm pretty sure it's unrelated to an insufficient waiting time. For other inputs, however, this seems to work fine.

I also tried running a separate cmd.exe here (where exe is svn.exe and args is the original arg string), but the hang still occurred:

string cmd = "cmd"; string arguments = "/S /C \"" + exe + " " + args + "\""; 

What could I be screwing up here, and how can I debug this external process stuff?

EDIT:

I'm just now getting around to addressing this. Mucho thanks to Jon Skeet for his suggestion, which indeed works great. I have another question about my method of handling this, though, since I'm a multi-threaded novice. I'd like suggestions on improving any glaring deficiencies or anything otherwise dumb. I ended up creating a small class that contains the stdout stream, a StringBuilder to hold the output, and a flag to tell when it's finished. Then I used ThreadPool.QueueUserWorkItem and passed in an instance of my class:

ProcessBufferHandler bufferHandler = new ProcessBufferHandler(proc.StandardOutput.BaseStream,                                                                           Encoding.UTF8); ThreadPool.QueueUserWorkItem(ProcessStream, bufferHandler);  proc.WaitForExit(ms); if (proc.HasExited) {     bufferHandler.Stop();     return bufferHandler.ReadToEnd(); } 

... and ...

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

This seems to work, but I'm doubtful that this is the best way. Is this reasonable? And what can I do to improve it?

like image 670
Chris Farmer Avatar asked Jan 13 '09 16:01

Chris Farmer


People also ask

What does process Start do?

Start(ProcessStartInfo)Starts the process resource that is specified by the parameter containing process start information (for example, the file name of the process to start) and associates the resource with a new Process component.

How do I start a process in VB net?

Start another application using your . NET code As a . NET method, Start has a series of overloads, which are different sets of parameters that determine exactly what the method does. The overloads let you specify just about any set of parameters that you might want to pass to another process when it starts.


1 Answers

One standard issue: the process could be waiting for you to read its output. Create a separate thread to read from its standard output while you're waiting for it to exit. It's a bit of a pain, but that may well be the problem.

like image 187
Jon Skeet Avatar answered Sep 29 '22 19:09

Jon Skeet