Peter Duniho
4/8/2008 9:01:00 PM
On Tue, 08 Apr 2008 12:13:22 -0700, John Brock <jbrock@panix.com> wrote:
> [...]
> I put the timeout in my function to mimic the timeout in the Shell()
> function, which will break if the program it is running hangs.
> The document you pointed me to seems to suggest (in the first
> example) that I can avoid deadlocks by calling WaitForExit after
> ReadToEnd().
Well, it's a bit unfortunate that the docs is written with the exact
wording it is, because there's really no need to call WaitForExit() after
you've called ReadToEnd(). ReadToEnd() won't return until the process has
ended, which is the same condition that causes WaitForExit() to return
immediately.
What the docs really should have said is "instead of p.WaitForExit" rather
than "before p.WaitForExit".
Now, as for your actual question...
> But what if the program hangs? How can I Read To End if the program
> I am running doesn't end, if it just stops writing to Stdout, but
> doesn't exit or close the stream? How would I ever even reach the
> WaitForExit() statement?
It wouldn't. If you are concerned about the possibility of the process
hanging, you can't use ReadToEnd().
> Am I still misunderstanding something? Or is there just no way to
> implement a fully functional Shell() style timeout without resorting
> to threads?
I guess that depends on your definition of "resorting to threads". I
don't think the word "resorting" is appropriate, because that implies some
negative consequence of using another thread. But no, if you want to be
able to implement a time-out as well as redirect the standard output,
you'll have to introduce a second thread to the implementation in some way.
There are a variety of ways you could do this:
-- Just start another thread that calls ReadToEnd() while your main
thread calls WaitForExit()
-- Call ReadToEnd() from your main thread, and create a timer (for
example, Threading.Timer), providing an elapsed event handler that
terminates the process
-- Call WaitForExit() in the main thread and use the asynchronous read
methods on the StreamReader.BaseStream (using the StandardOutput
StreamReader, of course).
The latter two would not require you to explicitly create a new thread,
but they still wind up using a second thread to handle the asynchronous
execution.
Pete